//========================================================================
//  SE5 AI Politics - Captain Kwok's Balance Mod v125+
//========================================================================
//
// 1. Load political memory
// 2. Process log events
// 3. Calculate anger towards other players as combination of events, messages, political relations and territory infringement
// 4. Reply to messages
// 5. Send messages
// 6. Vote on Alliance proposals
// 7. Save political memory
//
// Balance Mod Changes:
// --------------------
// v1.29 Changed - AI players were proposing treaty changes more than intended
//       Changed - Neutral AI players won't allow migration or colonization in treaties with other players
//       Fixed   - Contextual details were not always being added to diplomatic text
//       Changed - Added extra text to why a treaty might be rejected
//       Changed - AI players will also not accept sensor sharing if the target player is an enemy of one of their existing friends
//       Fixed   - Sometimes AI players would get in a counter-proposing circle since the concession check was too tight or pushing a specific treaty element
// v1.26 Fixed   - AI players were not always correctly remembering important diplomatic/message dates
//       Changed - Added extra flags for adding contextual details on treaty proposals and replies
//       Changed - Added miscellaneous messages for friends and enemies (general messages now relegated to new contacts, low level treaties)
// v1.25 Changed - Added in memory storage for when players break treaties and the number of times they break treaties
//       Added   - Incorporated cooperation levels into treaty diplomacy
//       Added   - More robust usefulness checks for various treaty elements
//       Added   - Increased instances of dynamic message text to help make AI motivations more clear
//       Changed - AI players will now remember broken treaty dates and the number of times a treaty is broken by a player
//       WIP     - AI players will now propose basic trades to allies
// v1.22 Fixed   - Typo in conditions for AI players to share combat reports per settings in ModAITreatySettings.txt
// v1.21 Added   - Support for adding extra AI speech in treaties, other diplomacy
//       Changed - Improved AI's ability to seek peace when it is struggling
//       Fixed   - AI was sending requests/demands sometimes based on shared combat logs that didn't involve them
//       Fixed   - AI players were not calculating anger correctly against strong human players
//       Changed - Added more race-to-race variability in anger for locations
//       Added   - Incorporated new ModAITreatySettings.txt file to add additional controls on AI treaty elements
//       Changed - AI empires were surrendering too readily in some cases
// v1.20 Fixed   - AI wasn't taking into account target priority when replying to a treaty request
//       Changed - Added anger modifier for stellar manipulation events [Should add in modifier for friend/activity]
//       Changed - Made improvements to how AI players fulfill requests
//       Fixed   - Strong AIs would offer the wrong treaty elements when countering the treaty of a weak player
// v1.19 Fixed   - Possible turn hang when an AI requested a gift
//       Changed - Increased rate of change for friendliness with non-MEE players after MEE is activated (v1.19a)
//       Fixed   - AI players were sometimes choosing the wrong tariff element (v1.19a)
//       Fixed   - AI empires would immediately break treaties with the mega evil player (v1.19c)
//       Changed - Made it easier for an AI to declare war against human players (v1.19d)
//       Changed - AI players will treat anger events against strong human players more seriously (v1.19d)
//       Fixed   - The AI was accepting bad trades (v1.19e)
//       Changed - Made some improvements to how the AI analyzes trades and gifts (v1.19e)
//       Fixed   - AI players in team mode would sometimes accept treaties from human players (v1.19g)
//       Changed - The AI will scrutinize their treaty status with other empires more closely for anger determination (v1.19h)
//       Changed - AI anger for combat events will be greater for the first incident in a turn (v1.19h)
//       Changed - Anger reduction for accepting a new treaty or treaty changes will be dependent on the "friendship" amount of the treaty (v1.19h)
//       Changed - Neutral players will only surrender to their primary enemy or primary friend (v1.19h)
//       Fixed   - Sometimes an AI wouldn't get angry over a negative event caused by a weaker player (v1.19h)
//       Changed - Made improvements to how the AI responds to certain requests (v1.19h)
//       Fixed   - Minor error in anger calculation for anger from other empire relations (v1.19h)
//       Changed - Incorporated more criteria for war/treaty diplomacy based on target priority (v1.19h)
//       Changed - Reduced AI's tendency for maintaining war or no treaty states with low priority players (v1.19h)
//       Changed - Revised anger calculation for enemy ships/colonies in the AI's territory (v1.19h)
//       Fixed   - Sometimes an AI could offer a lucrative treaty upon first contact (v1.19i)
//       Fixed   - Error in anger calculation (v1.19i)
//       Changed - AI players with Ancient Race trait will be less likely share maps (v1.19j)
//       Changed - AI will sometimes add anger for "friendly" player ships and colonies in its territory (v1.19j)
//       Changed - Additional anger penalty for mutual defense partners that maintain treaties with enemies (v1.19j)
//       Fixed   - Errors in variable references for anger due to political status with others (v1.19j)
//       Changed - Incorporated new variables to allow customized AI anger responses versus default values (v1.19j)
// v1.18 Changed - AI will remember when it was last asked to surrender
//       Changed - A weak AI asked to surrender might decide to surrender to another player
// v1.17 Added   - Memory value to note when a treaty was last proposed to a player
//       Changed - Refined request and warning messages to be more relevant
//       Fixed   - The AI was countering treaties when sometimes it wasn't intended
//       Changed - Improve how the AI evaluates a trade package
//       Changed - Adjusted some conditions for surrender
// v1.15 Changed - Implemented new anger system for the AI
//       Added   - New Fx[Is_Treaty_Element_Useful] for the AI to make better treaty decisions
//       Changed - The AI won't propose changes to a treaty if it makes the treaty less worthwhile
//       Fixed   - Sometimes the AI was sending treaty requests to individual members of an alliance
//       Changed - Adding a check to refuse treaty changes too soon after a previous treaty or treaty change
//       Fixed   - AI players were not always responding to treaty requests as intended
//       Changed - The AI will not surrender to a player that it is not at war with
//       Fixed   - Error in format in deadline dates for demands
// v1.14 Fixed   - Sometimes the AI would offer a treaty with no elements
// v1.13 Added   - Additional message details for detailing requests etc.
//       Added   - Note locations for AI demands against other players to remove their ships and colonies
// v1.12 Added   - Updated all diplomacy functions to support Alliances
//       Added   - New modifiers to help focus AI aggression against fewer targets
//       Fixed   - The AI was rejecting gifts when they should have accepted
//       Changed - Revised the conditions for sending demand or request messages
// v1.11 Fixed   - Sometimes the AI would offer a treaty with no elements if trying to end a war
//       Added   - New treaty type for peace treaties
//       Changed - Fx[Add_Anger_For_Political_State] also considers other empire's relations with AI's enemies/allies
//       Fixed   - The AI was not proposing changes to treaties as intended
// v1.10 Added   - The AI will break their treaty with the Mega Evil player
//       Added   - The AI will get angry with the Mega Evil player or non-AI players
//       Fixed   - Error in Fx[Compute_Max_Anger_For_Treaty_Elements] that sometimes prevented treaties from being accepted
//       Changed - Improved the AI's evaluation of gift and trade packages
// v1.09 Fixed   - Sometimes AI in team mode would break treaties with other AIs
//       Changed - Modified the effect of treaty status on the AI's anger calculation
//       Fixed   - AIs in team mode were offering treaties to non-AI players
//       Changed - Made a few modifications to how the AI interprets the value of gifts or trades
//       Fixed   - AIs were not adding items to gifts
// v1.08 Changed - Improved diversity in AI diplomacy
// v1.06 Fixed   - Non-Aggression treaty stipulation sometimes had no elements
//       Fixed   - Error in Mood Descriptions
//       Fixed   - AI would sometimes offer treaties when there were treaties already in place
//       Changed - Moved Fx[Compare_Score] to Script_AI_EnemyAnalysis.txt
//       Changed - Moved Fx[Compute_Fear] to Script_AI_EnemyAnalysis.txt
// v1.05 Changed - Tweaked conditions for Fx[Get_Warning_Message_To_Send]
//       Changed - Small tweaks to gift/trade package values, score comparisons
//       Fixed   - Anger ranges for treaty packages were not correct for typical anger levels
//       Added   - Fx[Compare_Score] and Fx[Calculate_Fear_Amount] to generate modifiers for diplomatic decisions
//       Added   - Fx[Get_Specific_Treaty_Element] for AI to choose appropriate treaty elements based on anger/fear
//       Fixed   - AI wasn't using the supplied synonym names for a treaty
//       Added   - Fx[Get_Treaty_Name] to provide a suitable name for the treaty
//       Updated - AI treaty proposal process
// v1.04 Changed - Tweaked a few treaty package options in Fx[Get_Treaty_Elements_To_Propose]
//       Fixed   - Races were not surrendering often or at all
// v1.03 Changed - Moved all treaty package options to Fx[Get_Treaty_Package_To_Propose]
//       Added   - Score conditions for accepting treaties and requests
//       Changed - Small tweaks for treaty type anger ranges
// v1.02 Fixed   - Error with exchange of trade items
// v1.01 Changed - Added a few more conditions to AI treaty proposals
// v0.99 Added   - New AI treaty proposal scheme that uses preset packages
// v0.98 Updated - Included various corrections from SE:V v1.16
// v0.97 Updated - Added more Alliance voting corrections from SE:V v1.15
// v0.94 Updated - Added Alliance voting fix from SE:V v1.12
//
// Balance Mod To-do list:
// -----------------------
// - Improvements to AI trade/gift functions (v130+) [WIP]
// - Implement more request types (v130+) [WIP]
// - Improve follow-up to requests (v130+) [WIP]
// - Implement more strategy in AI diplomatic decisions (v130+) [WIP]
//
// Script Function Requests:
// -------------------------
// - Nothing pending

//------------------------------------------------------------------------
// Global Constants
//------------------------------------------------------------------------
globalconst
endglobalconst

//------------------------------------------------------------------------
// Global Variables
//------------------------------------------------------------------------
globalvars

  lst_Politics_Memory_Player:                    longlist
  lst_Politics_Memory_Alliance:                  longlist
  lst_Politics_Memory_Date:                      longlist
  lst_Politics_Memory_System_Location:           longlist
  lst_Politics_Memory_Sector_Location:           longlist
  lst_Politics_Memory_Anger_Amount:              longlist
  lst_Politics_Memory_Entry_Type:                longlist
  lst_Politics_Memory_Entry_Value:               longlist

  lst_Message_Sent_To_Player:                    longlist
  lst_Message_Sent_To_Alliance:                  longlist

  lst_Requests_Type:                             longlist
  lst_Requests_Date:                             longlist
  lst_Requests_From_Plr:                         longlist
  lst_Requests_From_Alliance:                    longlist
  lst_Requests_Target_Plr:                       longlist
  lst_Requests_Target_Alliance:                  longlist
  lst_Requests_Target_Sys:                       longlist
  lst_Requests_Target_Sobj:                      longlist

  lst_Date_Treaty_Last_Offered:                  longlist
  lst_Date_Surrender_Last_Demanded:              longlist
  lst_Date_Last_Request_Made:                    longlist
  lst_Last_Request_Made_Type:                    longlist
  lst_Date_Last_Treaty_Broken:                   longlist
  lst_Num_Times_Treaty_Broken:                   longlist

  lng_Datafile_Speech_ID:                        long := 0
  
  str_Override_Message:                          string := ""
  str_Treaty_Reason:                             string := ""
  str_Reject_Reason:                             string := ""
  str_Counter_Reason:                            string := ""
  str_Break_Reason:                              string := ""
  str_Append_Message:                            string := ""

  gbl_is_neutral:                                boolean := FALSE
  gbl_is_peace_deal:                             boolean := FALSE
  gbl_accept_treaty:                             boolean := FALSE
  gbl_treaty_has_non_aggression:                 boolean := FALSE
  gbl_treaty_has_minefield_codes:                boolean := FALSE
  gbl_add_non_aggression:                        boolean := FALSE
  gbl_add_minefield_codes:                       boolean := FALSE

endglobalvars

//------------------------------------------------------------------------
// Forward Declarations
//------------------------------------------------------------------------
deffunc

function Load_Political_Memory returns boolean
params
end

function Save_Political_Memory returns boolean
params
end

function Add_Memory_Item returns boolean
params
  target_plr:                long
  target_alliance:           long
  anger_amt:                 long
  sys_loc:                   long
  sect_loc:                  long
  entry_type:                long
  type_value:                long
  replace_existing:          boolean
end

function Remove_Old_Requests returns boolean
params
end

function Remove_Old_Anger_Items returns boolean
params
end

function Process_Log_Events returns boolean
params
end

function Add_Anger_For_Political_State returns boolean
params
end

function Add_Anger_For_Locations returns boolean
params
end

function Calculate_Current_Anger returns boolean
params
end

function Calculate_Current_Anger_For_Entity returns long
params
  plr_id:                    long
  alliance_id:               long
end

function Reply_To_Messages returns boolean
params
end

function Reply_To_Propose_Treaty returns boolean
params
  log_id:                    long
end

function Compute_Counter_Treaty_Elements returns boolean
params
  log_id:                    long
  new_log_id:                long
  anger_towards_plr:         long
  fear_towards_plr:          long
end

function Compute_Max_Anger_For_Treaty_Elements returns long
params
  log_id:                    long
  anger_towards_plr:         long
  fear_towards_plr:          long
  coop_level:                long
  treaty_change:             boolean
end

function Get_Message_Text returns string
params
  send_msg_type:             long
  received_msg_type:         long
  to_plr:                    long
  to_alliance:               long
  other_plr:                 long
  other_alliance:            long
  proposed_treaty_name:      string
  proposed_alliance_name:    string
  target_system_id:          long
  target_sobj_id:            long
end

function Get_Message_Tone returns long
params
  to_plr:                    long
  to_alliance:               long
end

function Reply_To_Propose_Alliance returns boolean
params
  log_id:                    long
end

function Compute_Counter_Alliance_Elements returns boolean
params
  new_log_id:                long
  anger_towards_plr:         long
  fear_towards_plr:          long
end

function Compute_Max_Anger_For_Alliance_Elements returns long
params
  log_id:                    long
end

function Reply_To_Request_Join_Alliance returns boolean
params
  log_id:                    long
end

function Reply_To_General_Message returns boolean
params
  log_id:                    long
end

function Reply_To_Give_Gift returns boolean
params
  log_id:                    long
end

function Reply_To_Propose_Trade returns boolean
params
  log_id:                    long
end

function Calculate_Package_Value returns long
params
  log_id:                    long
  package_type:              long
  from_plr:                  long
end

function Change_Package_Any_Items_To_What_We_Want returns boolean
params
  log_id:                    long
  package_type:              long
end

function Reply_To_Request_Surrender returns boolean
params
  log_id:                    long
end

function Reply_To_Request_Gift returns boolean
params
  log_id:                    long
end

function Get_Gift_To_Give returns boolean
params
  log_id:                    long
  new_log_id:                long
end

function Get_Gift_Items_To_Request returns boolean
params
  new_log_id:                long
  to_plr:                    long
end

function Reply_To_General_Request returns boolean
params
  log_id:                    long
end

function Perform_Message_Demand returns boolean
params
  log_id:                    long
end

function Is_Specific_Request returns boolean
params
  msg_type:                  long
  target_id:                 long
  alliance_id:               long
end

function Send_Messages returns boolean
params
end

function Send_Message_To_Entity returns boolean
params
  to_plr:                    long
  to_alliance:               long
end

function Get_Treaty_To_Propose returns string
params
  to_plr:                    long
  to_alliance:               long
end

function Get_Treaty_Name returns string
params
  treaty_to_propose:         string
end

function Get_Treaty_Elements_To_Propose returns boolean
params
  new_log_id:                long
  to_plr:                    long
  to_alliance:               long
  new_msg_type:              long
  treaty_to_propose:         string
end

function Get_Specific_Treaty_Element returns long
params
  to_plr:                    long
  to_alliance:               long
  elem_type:                 long
  is_entity_A:               boolean
end

function Is_Treaty_Element_Useful returns boolean
params
  target_plr:                long
  elem_type:                 long
  elem_value:                long
end

function Get_Trade_To_Propose returns boolean
params
  to_plr:                    long
  new_log_id:                long
end


function Get_Warning_Message_To_Send returns long
params
  new_log_id:                long
  to_plr:                    long
  other_plr:                 long byref
  target_system_id:          long byref
  target_sobj_id:            long byref
end

function Alliance_Voting returns boolean
params
end

enddeffunc

//------------------------------------------------------------------------
// AI_Politics
//------------------------------------------------------------------------
function AI_Politics returns boolean
begin

  if Sys_Using_AI_Minister(sys_long_Player_ID, "Politics") then
    set lng_Datafile_Speech_ID := Sys_Load_Datafile(sys_long_Player_ID, str_Politics_Speech_Datafile_Filename)

    // Debug output
    call Sys_Debug_Print("Politics", "---------")
    call Sys_Debug_Print("Politics", "Politics:")

    call Load_Political_Memory()
    call Remove_Old_Anger_Items()
    call Remove_Old_Requests()
    call Process_Log_Events()
    call Add_Anger_For_Political_State()
    call Add_Anger_For_Locations()
    call Calculate_Current_Anger()

    // Debug output
    call Sys_Debug_Print("Politics", "----------")
    call Sys_Debug_Print("Politics", "Diplomacy:")

    // Debug text for mod treaty settings
    call Sys_Debug_Print("Politics", "  Mod AI Treaty Settings")
    call Sys_Debug_Print("Politics", "    - Allow Trade = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Allow_Trade))
    call Sys_Debug_Print("Politics", "    - Offer Trade = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Offer_Trade))
    call Sys_Debug_Print("Politics", "    - Allow Migration = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Allow_Migration))
    call Sys_Debug_Print("Politics", "    - Offer Migration = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Offer_Migration))
    call Sys_Debug_Print("Politics", "    - Allow Colonization = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Allow_Colonization))
    call Sys_Debug_Print("Politics", "    - Offer Colonization = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Offer_Colonization))
    call Sys_Debug_Print("Politics", "    - Allow Share Technology = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Allow_Share_Technology))
    call Sys_Debug_Print("Politics", "    - Offer Share Technology = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Offer_Share_Technology))
    call Sys_Debug_Print("Politics", "    - Allow Share Maps = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Allow_Share_Maps))
    call Sys_Debug_Print("Politics", "    - Offer Share Maps = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Offer_Share_Maps))
    call Sys_Debug_Print("Politics", "    - Allow Share Comm Channels = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Allow_Share_Comm_Channels))
    call Sys_Debug_Print("Politics", "    - Offer Share Comm Channels = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Offer_Share_Comm_Channels))
    call Sys_Debug_Print("Politics", "    - Allow Share Espionage Info = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Allow_Share_Espionage_Info))
    call Sys_Debug_Print("Politics", "    - Offer Share Espionage Info = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Offer_Share_Espionage_Info))
    call Sys_Debug_Print("Politics", "    - Allow Share Sensor Info = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Allow_Share_Sensor_Info))
    call Sys_Debug_Print("Politics", "    - Offer Share Sensor Info = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Offer_Share_Sensor_Info))
    call Sys_Debug_Print("Politics", "    - Allow Share Vehicle Designs = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Allow_Share_Vehicle_Designs))
    call Sys_Debug_Print("Politics", "    - Offer Share Vehicle Designs = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Offer_Share_Vehicle_Designs))
    call Sys_Debug_Print("Politics", "    - Allow Share Combat Reports = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Allow_Share_Combat_Reports))
    call Sys_Debug_Print("Politics", "    - Offer Share Combat Reports = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Offer_Share_Combat_Reports))
    call Sys_Debug_Print("Politics", "    - Allow Share Minefield Codes = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Allow_Share_Minefield_Codes))
    call Sys_Debug_Print("Politics", "    - Offer Share Minefield Codes = " + Sys_Convert_Boolean_To_String(bool_ModAITreatySetting_Offer_Share_Minefield_Codes))

    // Don't let Neutral AIs don't do certain types of diplomacy regardless of game settings (migration, allow colonization)
    if Sys_Are_We_Neutral_Empire(sys_long_Player_ID) then
      set bool_ModAITreatySetting_Allow_Migration := FALSE
      set bool_ModAITreatySetting_Offer_Migration := FALSE
      set bool_ModAITreatySetting_Allow_Colonization := FALSE
      set bool_ModAITreatySetting_Offer_Colonization := FALSE
      set bool_ModAITreatySetting_Allow_Share_Minefield_Codes := FALSE
      set bool_ModAITreatySetting_Offer_Share_Minefield_Codes := FALSE
    endif

    call Reply_To_Messages()
    call Send_Messages()
    call Alliance_Voting()
    call Save_Political_Memory()

    call Sys_Unload_Datafile(lng_Datafile_Speech_ID)
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Load_Political_Memory
//------------------------------------------------------------------------
function Load_Political_Memory returns boolean
vars
  anger_count:               long
  requests_count:            long
  plr_count:                 long
  index:                     long
  base_index:                long
begin

  // Load our previous anger items from memory
  set anger_count := Sys_Get_AI_Storage_Long(sys_long_Player_ID, 1, 5)

  if (anger_count > 0) then
    for index := 1 to anger_count do
      set base_index := ((index - 1) * 8)
      call lst_Politics_Memory_Player.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 2, base_index + 1))
      call lst_Politics_Memory_Alliance.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 2, base_index + 2))
      call lst_Politics_Memory_Date.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 2, base_index + 3))
      call lst_Politics_Memory_System_Location.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 2, base_index + 4))
      call lst_Politics_Memory_Sector_Location.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 2, base_index + 5))
      call lst_Politics_Memory_Anger_Amount.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 2, base_index + 6))
      call lst_Politics_Memory_Entry_Type.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 2, base_index + 7))
      call lst_Politics_Memory_Entry_Value.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 2, base_index + 8))
    endfor
  endif

  // Load our previous requests from memory
  set requests_count := Sys_Get_AI_Storage_Long(sys_long_Player_ID, 1, 6)

  if (requests_count > 0) then
    for index := 1 to requests_count do
      set base_index := ((index - 1) * 8)
      call lst_Requests_Type.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 3, base_index + 1))
      call lst_Requests_Date.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 3, base_index + 2))
      call lst_Requests_From_Plr.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 3, base_index + 3))
      call lst_Requests_From_Alliance.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 3, base_index + 4))
      call lst_Requests_Target_Plr.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 3, base_index + 5))
      call lst_Requests_Target_Alliance.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 3, base_index + 6))
      call lst_Requests_Target_Sys.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 3, base_index + 7))
      call lst_Requests_Target_Sobj.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 3, base_index + 8))
    endfor
  endif

  // Load from memory the dates of our last treaty offered, last surrender, type and date of request and last broken treaty and number of times treaties have been broken
  set plr_count := Sys_Get_Number_Of_Players()

  if (plr_count > 0) then
    for index := 1 to plr_count do
      set base_index := ((index - 1) * 6)
      call lst_Date_Treaty_Last_Offered.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 4, base_index + 1))
      call lst_Date_Surrender_Last_Demanded.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 4, base_index + 2))
      call lst_Date_Last_Request_Made.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 4, base_index + 3))
      call lst_Last_Request_Made_Type.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 4, base_index + 4))
      call lst_Date_Last_Treaty_Broken.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 4, base_index + 5))
      call lst_Num_Times_Treaty_Broken.add(Sys_Get_AI_Storage_Long(sys_long_Player_ID, 4, base_index + 6))
    endfor
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Save_Political_Memory
//------------------------------------------------------------------------
function Save_Political_Memory returns boolean
vars
  anger_count:               long
  anger_amt:                 long
  requests_count:            long
  plr_count:                 long
  loop_index:                long
  index:                     long
  base_index:                long
  remove_entry:              boolean := FALSE
begin

  // Save our anger items in our political memory
  set anger_count := lst_Politics_Memory_Player.count()
  call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 1, 5, anger_count)

  if (anger_count > 0) then
    for index := 1 to anger_count do
      set base_index := ((index - 1) * 8)
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 2, base_index + 1, lst_Politics_Memory_Player.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 2, base_index + 2, lst_Politics_Memory_Alliance.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 2, base_index + 3, lst_Politics_Memory_Date.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 2, base_index + 4, lst_Politics_Memory_System_Location.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 2, base_index + 5, lst_Politics_Memory_Sector_Location.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 2, base_index + 6, lst_Politics_Memory_Anger_Amount.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 2, base_index + 7, lst_Politics_Memory_Entry_Type.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 2, base_index + 8, lst_Politics_Memory_Entry_Value.get(index))
    endfor
  endif

  // Save our requests in our political memory
  set requests_count := lst_Requests_Type.count()

  call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 1, 6, requests_count)

  if (requests_count > 0) then
    for index := 1 to requests_count do
      set base_index := ((index - 1) * 8)
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 3, base_index + 1, lst_Requests_Type.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 3, base_index + 2, lst_Requests_Date.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 3, base_index + 3, lst_Requests_From_Plr.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 3, base_index + 4, lst_Requests_From_Alliance.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 3, base_index + 5, lst_Requests_Target_Plr.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 3, base_index + 6, lst_Requests_Target_Alliance.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 3, base_index + 7, lst_Requests_Target_Sys.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 3, base_index + 8, lst_Requests_Target_Sobj.get(index))
    endfor
  endif

  // Save the dates of our last treaty offered, last received surrender demand, last request type and last treaty broken from each player
  set plr_count := Sys_Get_Number_Of_Players()

  if (plr_count > 0) then
    for index := 1 to plr_count do
      set base_index := ((index - 1) * 6)
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 4, base_index + 1, lst_Date_Treaty_Last_Offered.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 4, base_index + 2, lst_Date_Surrender_Last_Demanded.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 4, base_index + 3, lst_Date_Last_Request_Made.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 4, base_index + 4, lst_Last_Request_Made_Type.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 4, base_index + 5, lst_Date_Last_Treaty_Broken.get(index))
      call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 4, base_index + 6, lst_Num_Times_Treaty_Broken.get(index))
    endfor
  endif

  // Save our primary enemy and friend
  call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 1, 3, lng_Politics_Primary_Enemy)
  call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 1, 4, lng_Politics_Primary_Friend)

  // Save our AI categorization
  call Sys_Set_AI_Storage_Long(sys_long_Player_ID, 1, 11, lng_AI_Categorization)

  return TRUE
end

//------------------------------------------------------------------------
// Remove_Old_Anger_Items
//------------------------------------------------------------------------
function Remove_Old_Anger_Items returns boolean
params
vars
  list_count:                long
  list_index:                long := 0
  anger_amt:                 long
  remove_entry:              boolean := FALSE
begin

  // Get the number of anger items
  set list_count := lst_Politics_Memory_Player.count()

  // Reduce our anger amounts for each item
  if (list_count > 0) then
    loop
      set list_index := list_index + 1
      set remove_entry := FALSE
      // For anger items from events or messages, decrease their anger contribution each turn
      if (lst_Politics_Memory_Entry_Type.get(list_index) = MEMORY_ITEM_TYPE_LOG_EVENT) or (lst_Politics_Memory_Entry_Type.get(list_index) = MEMORY_ITEM_TYPE_MESSAGE_RECEIVED) then
        set anger_amt := lst_Politics_Memory_Anger_Amount.get(list_index)

        if (anger_amt >= -1) and (anger_amt <= 1) then
          set remove_entry := TRUE
        else
          if (anger_amt < 0) then
            set anger_amt := anger_amt + 1
            call lst_Politics_Memory_Anger_Amount.set(list_index, anger_amt)
          else
            set anger_amt := anger_amt - 1
            call lst_Politics_Memory_Anger_Amount.set(list_index, anger_amt)
          endif
        endif

        // Delete items from our memory that are no longer contributing anger
        if (remove_entry) then
          call lst_Politics_Memory_Player.delete(list_index)
          call lst_Politics_Memory_Alliance.delete(list_index)
          call lst_Politics_Memory_Date.delete(list_index)
          call lst_Politics_Memory_System_Location.delete(list_index)
          call lst_Politics_Memory_Sector_Location.delete(list_index)
          call lst_Politics_Memory_Anger_Amount.delete(list_index)
          call lst_Politics_Memory_Entry_Type.delete(list_index)
          call lst_Politics_Memory_Entry_Value.delete(list_index)
          set list_index := list_index - 1
          set list_count := list_count - 1
        endif
      endif
      exitwhen (list_index >= list_count) or (list_count = 0)
    endloop
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Remove_Old_Requests
//------------------------------------------------------------------------
function Remove_Old_Requests returns boolean
params
vars
  list_count:                long
  list_index:                long
  request_date:              long
begin

  // Remove old requests that are beyond our time to honor requests
  set list_count := lst_Requests_Type.count()

  // Debug output
  call Sys_Debug_Print("Politics", "---------")
  call Sys_Debug_Print("Politics", "Requests:")

  if (list_count > 0) then
    set list_index := 0
    loop
      set list_index := list_index + 1
      set request_date := lst_Requests_Date.get(list_index)

      // Debug output
      call Sys_Debug_Print("Politics", "  - Request Type = " + Get_Message_Type(lst_Requests_type.get(list_index)))
      call Sys_Debug_Print("Politics", "    - Request Date = " + Sys_Convert_Long_To_String(lst_Requests_Date.get(list_index)))
      call Sys_Debug_Print("Politics", "    - Request Empire = " + Sys_Empire_Get_Empire_Name(lst_Requests_From_Plr.get(list_index)))
      call Sys_Debug_Print("Politics", "    - Target Empire = " + Sys_Empire_Get_Empire_Name(lst_Requests_Target_Plr.get(list_index)))
      call Sys_Debug_Print("Politics", "    - Target Sys = " + Sys_Get_Solar_System_Name(lst_Requests_Target_Sys.get(list_index)))
      call Sys_Debug_Print("Politics", "    - Target Sobj = " + Sys_Get_Space_Object_Name(lst_Requests_Target_Sobj.get(list_index)))

      // Delete requests that are out of date
      if ((request_date + lng_Politics_Max_Time_To_Honor_A_Request) < sys_long_Game_Date) then
        call lst_Requests_Type.delete(list_index)
        call lst_Requests_Date.delete(list_index)
        call lst_Requests_From_Plr.delete(list_index)
        call lst_Requests_From_Alliance.delete(list_index)
        call lst_Requests_Target_Plr.delete(list_index)
        call lst_Requests_Target_Alliance.delete(list_index)
        call lst_Requests_Target_Sys.delete(list_index)
        call lst_Requests_Target_Sobj.delete(list_index)
        set list_index := list_index - 1
        set list_count := list_count - 1
        // Debug output
        call Sys_Debug_Print("Politics", "  - Request removed!")
      endif
      exitwhen (list_index >= list_count) or (list_count = 0)
    endloop
  else
    // Debug output
    call Sys_Debug_Print("Politics", "  - None")
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Add_Memory_Item
//------------------------------------------------------------------------
function Add_Memory_Item returns boolean
params
  target_plr:                long
  target_alliance:           long
  anger_amt:                 long
  sys_loc:                   long
  sect_loc:                  long
  entry_type:                long
  type_value:                long
  replace_existing:          boolean
vars
  memory_count:              long
  memory_index:              long := 0
  add_item:                  boolean := TRUE
begin

  // Get the number of memory items
  set memory_count := lst_Politics_Memory_Player.count()

  // Update one of our previous anger items with its new value
  if (replace_existing) and (memory_count > 0) then
    loop
      set memory_index := memory_index + 1
      // Add anger item to our list
      if ((target_plr > 0) and (lst_Politics_Memory_Player.get(memory_index) = target_plr)) or ((target_alliance > 0) and (lst_Politics_Memory_Alliance.get(memory_index) = target_alliance)) then
        if (lst_Politics_Memory_Entry_Type.get(memory_index) = entry_type) then
          call lst_Politics_Memory_Player.set(memory_index, target_plr)
          call lst_Politics_Memory_Date.set(memory_index, sys_long_Game_Date)
          call lst_Politics_Memory_System_Location.set(memory_index, sys_loc)
          call lst_Politics_Memory_Sector_Location.set(memory_index, sect_loc)
          call lst_Politics_Memory_Entry_Type.set(memory_index, entry_type)
          call lst_Politics_Memory_Entry_Value.set(memory_index, type_value)
          call lst_Politics_Memory_Anger_Amount.set(memory_index, anger_amt)
          set add_item := FALSE
        endif
      endif
      exitwhen (not add_item) or (memory_index >= memory_count)
    endloop
  endif

  // Add a new anger item to memory
  if (add_item) then
    call lst_Politics_Memory_Player.add(target_plr)
    call lst_Politics_Memory_Alliance.add(target_alliance)
    call lst_Politics_Memory_Date.add(sys_long_Game_Date)
    call lst_Politics_Memory_System_Location.add(sys_loc)
    call lst_Politics_Memory_Sector_Location.add(sect_loc)
    call lst_Politics_Memory_Anger_Amount.add(anger_amt)
    call lst_Politics_Memory_Entry_Type.add(entry_type)
    call lst_Politics_Memory_Entry_Value.add(type_value)
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Process_Log_Events
//------------------------------------------------------------------------
function Process_Log_Events returns boolean
vars
  lst_log_entries:           longlist
  list_count:                long
  list_index:                long
  list_pos:                  long
  log_id:                    long
  log_type:                  long
  plr_index:                 long
  plr_caused:                long
  alliance_caused:           long
  msg_type:                  long
  anger_amt:                 long
  sys_loc:                   long
  sect_loc:                  long
  this_date:                 long
  memory_added:              boolean
  other_plr1:                long
  other_plr2:                long
  other_plr3:                long
  other_plr4:                long
  our_alliance_id:           long
  colony_lost:               long
  intel_count:               long
  ground_combat_count:       long
  ground_combat_count_plr:   longlist
  space_combat_count:        long
  space_combat_count_plr:    longlist
begin

  // Are we part of an alliance?
  set our_alliance_id := Sys_Empire_Politics_In_Alliance_ID(sys_long_Player_ID)

  // Get our current log entries
  call Sys_Empire_Log_Get_Log_Entries_For_This_Turn(sys_long_Player_ID, lst_log_entries)
  call ground_combat_count_plr.fill(Sys_Get_Number_Of_Players(), 0)
  call space_combat_count_plr.fill(Sys_Get_Number_Of_Players(), 0)

  // Go through our log entries and look for anger items to add to our memory
  set list_count := lst_log_entries.count()

  if (list_count > 0) then
    for list_index := 1 to list_count do
      set log_id := lst_log_entries.get(list_index)
      set log_type := Sys_Empire_Log_Get_Log_Entry_Type(sys_long_Player_ID, log_id)
      set sys_loc := Sys_Empire_Log_Get_Log_Entry_System_Location(sys_long_Player_ID, log_id)
      set sect_loc := Sys_Empire_Log_Get_Log_Entry_Sector_Location(sys_long_Player_ID, log_id)
      set plr_caused := Sys_Empire_Log_Get_Log_Entry_Caused_By_Player(sys_long_Player_ID, log_id)
      set alliance_caused := Sys_Empire_Log_Get_Log_Entry_Caused_By_Alliance(sys_long_Player_ID, log_id)
      set msg_type := 0
      set anger_amt := 0
      set memory_added := FALSE

      // Add anger for ground combat
      if (log_type = LOG_TYPE_GROUND_COMBAT_DEFENSE_LOST) or (log_type = LOG_TYPE_GROUND_COMBAT_DEFENSE_WON) or (log_type = LOG_TYPE_GROUND_COMBAT_OFFENSE_LOST) or (log_type = LOG_TYPE_GROUND_COMBAT_STALEMATE) then
        set list_pos := lst_Politics_Anger_Event_Type.indexof(log_type)
        
        if (list_pos > 0) then
          set anger_amt := lst_Politics_Anger_Event_Amount.get(list_pos)
          call Sys_Get_Log_Players_In_Combat(sys_long_Player_ID, log_id, other_plr1, other_plr2, other_plr3, other_plr4)

          // Add extra anger if we lost a colony
          set colony_lost := Sys_Log_Was_Colony_Lost(sys_long_Player_ID, log_id)
          case colony_lost
            1:  
              set anger_amt := anger_amt + Sys_Get_Random_Long(2, 3 + lng_AI_Categorization)
            2:  
              set anger_amt := anger_amt + Sys_Get_Random_Long(3, 4 + lng_AI_Categorization)
          endcase

          if (plr_caused <> sys_long_player_ID) and (plr_caused > 0) then
            set ground_combat_count := ground_combat_count_plr.get(plr_caused)
            // Count the number of ground combats caused by each player against us
            call ground_combat_count_plr.set(plr_caused, ground_combat_count + 1)
            // Add extra anger for the first combat incident with a player each turn
            if (ground_combat_count = 1) then
              set anger_amt := anger_amt * 2
            endif
          endif

          // Add anger for other players that were involved
          if (other_plr1 > 0) and (other_plr1 <> sys_long_Player_ID) and Is_Player_Enemy(sys_long_Player_ID, other_plr1, FALSE) then
            set memory_added := Add_Memory_Item(other_plr1, 0, anger_amt, sys_loc, sect_loc, MEMORY_ITEM_TYPE_LOG_EVENT, log_type, FALSE)
          endif
          if (other_plr2 > 0) and (other_plr2 <> sys_long_Player_ID) and Is_Player_Enemy(sys_long_Player_ID, other_plr2, FALSE) then
            set memory_added := Add_Memory_Item(other_plr2, 0, anger_amt, sys_loc, sect_loc, MEMORY_ITEM_TYPE_LOG_EVENT, log_type, FALSE)
          endif
          if (other_plr3 > 0) and (other_plr3 <> sys_long_Player_ID) and Is_Player_Enemy(sys_long_Player_ID, other_plr3, FALSE) then
            set memory_added := Add_Memory_Item(other_plr3, 0, anger_amt, sys_loc, sect_loc, MEMORY_ITEM_TYPE_LOG_EVENT, log_type, FALSE)
          endif
          if (other_plr4 > 0) and (other_plr4 <> sys_long_Player_ID) and Is_Player_Enemy(sys_long_Player_ID, other_plr4, FALSE) then
            set memory_added := Add_Memory_Item(other_plr4, 0, anger_amt, sys_loc, sect_loc, MEMORY_ITEM_TYPE_LOG_EVENT, log_type, FALSE)
          endif
        endif
      endif

      // Add anger for space combat
      if (log_type = LOG_TYPE_SPACE_COMBAT_DEFENSE_LOST) or (log_type = LOG_TYPE_SPACE_COMBAT_DEFENSE_WON) or (log_type = LOG_TYPE_SPACE_COMBAT_OFFENSE_LOST) or (log_type = LOG_TYPE_SPACE_COMBAT_STALEMATE) then
        set list_pos := lst_Politics_Anger_Event_Type.indexof(log_type)

        if (list_pos > 0) then
          set anger_amt := lst_Politics_Anger_Event_Amount.get(list_pos)

          // Add extra anger if we lost a colony
          set colony_lost := Sys_Log_Was_Colony_Lost(sys_long_Player_ID, log_id)
          case colony_lost
            1:
              set anger_amt := anger_amt + Sys_Get_Random_Long(2, 3 + lng_AI_Categorization)
            2:
              set anger_amt := anger_amt + Sys_Get_Random_Long(3, 4 + lng_AI_Categorization)
          endcase

          if (plr_caused <> sys_long_player_ID) and (plr_caused > 0) then
            set space_combat_count := space_combat_count_plr.get(plr_caused)
            // Count the number of space combats caused by each player against us
            call space_combat_count_plr.set(plr_caused, space_combat_count + 1)
            // Add extra anger for the first combat incident with a player each turn
            if (space_combat_count = 1) then
              set anger_amt := anger_amt * 2
            endif
          endif

          // Add anger for other players that were involved
          call Sys_Get_Log_Players_In_Combat(sys_long_Player_ID, log_id, other_plr1, other_plr2, other_plr3, other_plr4)
          if (other_plr1 > 0) and (other_plr1 <> sys_long_Player_ID) and Is_Player_Enemy(sys_long_Player_ID, other_plr1, FALSE) then
            set memory_added := Add_Memory_Item(other_plr1, 0, anger_amt, sys_loc, sect_loc, MEMORY_ITEM_TYPE_LOG_EVENT, log_type, FALSE)
          endif
          if (other_plr2 > 0) and (other_plr2 <> sys_long_Player_ID) and Is_Player_Enemy(sys_long_Player_ID, other_plr2, FALSE) then
            set memory_added := Add_Memory_Item(other_plr2, 0, anger_amt, sys_loc, sect_loc, MEMORY_ITEM_TYPE_LOG_EVENT, log_type, FALSE)
          endif
          if (other_plr3 > 0) and (other_plr3 <> sys_long_Player_ID) and Is_Player_Enemy(sys_long_Player_ID, other_plr3, FALSE) then
            set memory_added := Add_Memory_Item(other_plr3, 0, anger_amt, sys_loc, sect_loc, MEMORY_ITEM_TYPE_LOG_EVENT, log_type, FALSE)
          endif
          if (other_plr4 > 0) and (other_plr4 <> sys_long_Player_ID) and Is_Player_Enemy(sys_long_Player_ID, other_plr4, FALSE) then
            set memory_added := Add_Memory_Item(other_plr4, 0, anger_amt, sys_loc, sect_loc, MEMORY_ITEM_TYPE_LOG_EVENT, log_type, FALSE)
          endif
        endif
      endif

      // Are we being hit with lots of intel?
      if (log_type = LOG_TYPE_SABOTAGE_AGAINST_US) or (log_type = LOG_TYPE_ESPIONAGE_AGAINST_US) then
        set intel_count := intel_count + 1
        if (intel_count >= 5) then
          set bool_Enemy_Intel_Overload := TRUE
        endif
      endif

      if (log_type = LOG_TYPE_MINE_EXPLOSION) then
        // Player responsible
        set plr_caused := Get_Mine_Group_Owner(sys_loc, sect_loc)
        // Don't count us!
        if (plr_caused = sys_long_Player_ID) then
          set plr_caused := 0
        endif
      endif

      // Add anger for other items in our log
      if (not memory_added) then
        // Add anger for non-combat events in our log
        if ((plr_caused > 0) and (plr_caused <> sys_long_Player_ID)) or ((alliance_caused > 0) and (alliance_caused <> our_alliance_id)) then
          set list_pos := lst_Politics_Anger_Event_Type.indexof(log_type)

          if (list_pos > 0) then
            set anger_amt := lst_Politics_Anger_Event_Amount.get(list_pos)
            // Modify our anger for stellar manipulation events depending on how they affected us
            case log_type
              LOG_TYPE_MINE_EXPLOSION:
                // Add extra anger for minefield explosions caused by players we have treaties with
                if (plr_caused > 0) then
                  if (Sys_Empire_Politics_Get_Status_With_Player(sys_long_Player_ID, plr_caused) = POLITICAL_STATUS_TYPE_TREATY) then
                    set anger_amt := anger_amt * 3
                  else
                    // Nothing
                  endif
                  // Temp debug
                  call Sys_Debug_Print("Politics", "    - " + Sys_Empire_Get_Empire_Name(plr_caused) + " (Treaty) caused mine explosion!")
                  call Sys_Debug_Print("Politics", "    - " + Sys_Get_Solar_System_Name(sys_loc) + " " + Convert_Sector_To_String(sect_loc))
                endif
              LOG_TYPE_STELLAR_BLACK_HOLE_CREATED:
                // Increase anger if we have nearby colonies
                if Do_We_Have_Colonies_In_Adjacent_Systems(sys_loc) then
                  set anger_amt := anger_amt * 3
                endif
              LOG_TYPE_STELLAR_NEBULAE_CREATED:
                // Increase anger if we have nearby colonies
                if Do_We_Have_Colonies_In_Adjacent_Systems(sys_loc) then
                  set anger_amt := anger_amt * 3
                endif
              LOG_TYPE_STELLAR_PLANET_DESTROYED:
                if (lst_AI_Our_Colony_Systems.indexof(sys_loc) > 0) then
                  set anger_amt := anger_amt * 3
                else
                  // Increase anger if we have nearby colonies
                  if Do_We_Have_Colonies_In_Adjacent_Systems(sys_loc) then
                    set anger_amt := anger_amt * 2
                  endif
                endif
              LOG_TYPE_STELLAR_STORM_CREATED:
                if (lst_AI_Our_Colony_Systems.indexof(sys_loc) > 0) then
                  set anger_amt := anger_amt * 3
                else
                  // Increase anger if we have nearby colonies
                  if Do_We_Have_Colonies_In_Adjacent_Systems(sys_loc) then
                    set anger_amt := anger_amt * 2
                  endif
                endif
              LOG_TYPE_STELLAR_STAR_DESTROYED:
                if (lst_AI_Our_Colony_Systems.indexof(sys_loc) > 0) then
                  set anger_amt := anger_amt * 3
                else
                  // Increase anger if we have nearby colonies
                  if Do_We_Have_Colonies_In_Adjacent_Systems(sys_loc) then
                    set anger_amt := anger_amt * 2
                  endif
                endif
              LOG_TYPE_STELLAR_WP_CLOSED:
                if (lst_AI_Our_Colony_Systems.indexof(sys_loc) > 0) then
                  set anger_amt := anger_amt * 2
                endif
              LOG_TYPE_STELLAR_WP_OPENED:
                if (lst_AI_Our_Colony_Systems.indexof(sys_loc) > 0) then
                  set anger_amt := anger_amt * 2
                endif
            endcase

            // Add extra anger for events caused by our primary enemy or the Mega Evil player
            if (plr_caused = lng_Politics_Primary_Enemy) or Sys_Empire_Politics_Is_Player_The_Ultimate_Evil(sys_long_Player_ID, plr_caused) then
              if (anger_amt > 0) then
                set anger_amt := anger_amt * 2
              endif
            endif

            // Add extra anger for human players based on difficulty
            if (not Sys_Are_We_Computer_Player(plr_caused)) then
              case lng_AI_Difficulty
                AI_DIFFICULTY_EASY:
                  set anger_amt := anger_amt + 1
                AI_DIFFICULTY_MEDIUM:
                  set anger_amt := anger_amt + 2
                AI_DIFFICULTY_HARD:
                  set anger_amt := anger_amt + 3
              endcase
            endif

            // Add the anger to our memory for the log event
            if (plr_caused > 0) then
              set memory_added := Add_Memory_Item(plr_caused, 0, anger_amt, sys_loc, sect_loc, MEMORY_ITEM_TYPE_LOG_EVENT, log_type, FALSE)
            else
              set memory_added := Add_Memory_Item(0, alliance_caused, anger_amt, sys_loc, sect_loc, MEMORY_ITEM_TYPE_LOG_EVENT, log_type, FALSE)
            endif
          endif
        endif
        // Add anger for diplomatic messages in our log
        if (log_type = LOG_TYPE_MESSAGE) then
          set msg_type := Sys_Empire_Log_Get_Log_Entry_Message_Type(sys_long_Player_ID, log_id)
          set plr_caused := Sys_Empire_Log_Get_Log_Entry_Message_From_Player(sys_long_Player_ID, log_id)
          set alliance_caused := Sys_Empire_Log_Get_Log_Entry_Message_From_Alliance(sys_long_Player_ID, log_id)
          set list_pos := lst_Politics_Anger_Message_Type.indexof(msg_type)

          if (list_pos > 0) and (plr_caused <> sys_long_Player_ID) then
            set anger_amt := lst_Politics_Anger_Message_Amount.get(list_pos)
            // Don't reduce our anger too much for "non-friendship" treaties
            if (msg_type = POLITICS_MSG_ACCEPT_TREATY) or (msg_type = POLITICS_MSG_ACCEPT_TREATY_CHANGES) then
              if (lst_Politics_Friendship_Towards_Player.get(plr_caused) < 5) then
                set anger_amt := Sys_Divide_Long(anger_amt, 2)
              endif
            endif
            // Add the anger to our memory for the message
            if (plr_caused > 0) then
              set memory_added := Add_Memory_Item(plr_caused, 0, anger_amt, 0, 0, MEMORY_ITEM_TYPE_MESSAGE_RECEIVED, msg_type, FALSE)
            else
              set memory_added := Add_Memory_Item(0, alliance_caused, anger_amt, 0, 0, MEMORY_ITEM_TYPE_MESSAGE_RECEIVED, msg_type, FALSE)
            endif
          endif
        endif
      endif
    endfor
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Add_Anger_For_Political_State
//------------------------------------------------------------------------
function Add_Anger_For_Political_State returns boolean
vars
  our_alliance_id:           long
  list_count:                long
  list_index:                long
  plr_index:                 long
  friendship_pts:            long
  pol_status:                long
  pol_status_time_mod:       long
  anger_amt:                 long
  other_anger_amt:           long
  min_anger_amt:             long
  max_anger_amt:             long
  is_mutual_defense_partner: boolean
  is_other_known:            boolean
  is_other_friend:           boolean
  is_other_enemy:            boolean
begin

  // Are we in an alliance?
  set our_alliance_id := Sys_Empire_Politics_In_Alliance_ID(sys_long_Player_ID)

  // Cycle through the player list to determine political anger towards each known empire
  set list_count := Sys_Get_Number_Of_Players()

  if (list_count > 0) then
    for list_index := 1 to list_count do
      if (list_index <> sys_long_Player_ID) then
        set pol_status := Sys_Empire_Politics_Get_Status_With_Player(sys_long_Player_ID, list_index)
        set pol_status_time_mod := Sys_Trunc(Sys_Empire_Politics_Get_Status_Time_With_Player(sys_long_Player_ID, list_index) ^ 0.5)
        set is_mutual_defense_partner := Do_We_Have_Treaty_Element_With_Player(list_index, TREATY_ELEMENT_TYPE_MUTUAL_DEFENSE_PACT, FALSE, 0)
        set friendship_pts := lst_Politics_Friendship_Towards_Player.get(list_index)
        set min_anger_amt := lng_Politics_Min_Anger_For_Political_Status + Sys_Get_Random_Long(lng_Politics_Min_Anger_Flux, lng_Politics_Max_Anger_Flux)
        set max_anger_amt := lng_Politics_Max_Anger_For_Political_Status + Sys_Get_Random_Long(lng_Politics_Min_Anger_Flux, lng_Politics_Max_Anger_Flux)
        set anger_amt := 0

        // Calculate our anger with the current player
        case pol_status
          POLITICAL_STATUS_TYPE_KNOWN:
            set anger_amt := lng_Politics_Anger_Amount_For_Known_Status_Time * pol_status_time_mod
          POLITICAL_STATUS_TYPE_TREATY:
            if (friendship_pts > lng_Politics_Max_Friendship_Pts_For_Anger) then
              // Add less anger for good friends
              set anger_amt := lng_Politics_Anger_Amount_For_Treaty_Status_Time * pol_status_time_mod
            else
              set anger_amt := Sys_Divide_Long(lng_Politics_Anger_Amount_For_Treaty_Status_Time * pol_status_time_mod, 2)
            endif
          POLITICAL_STATUS_TYPE_WAR:
            set anger_amt := lng_Politics_Anger_Amount_For_War_Status_Time * pol_status_time_mod
        endcase
        // Cap
        set anger_amt := Sys_Min_Long(anger_amt, max_anger_amt)
        set anger_amt := Sys_Max_Long(anger_amt, min_anger_amt)
        // Add anger amount to our memory for political status
        call Add_Memory_Item(list_index, 0, anger_amt, 0, 0, MEMORY_ITEM_TYPE_POLITICAL_STATUS, pol_status, TRUE)

        // Reset our anger variables
        set min_anger_amt := lng_Politics_Min_Anger_For_Political_Status_With_Others + Sys_Get_Random_Long(lng_Politics_Min_Anger_Flux, lng_Politics_Max_Anger_Flux)
        set max_anger_amt := lng_Politics_Max_Anger_For_Political_Status_With_Others + Sys_Get_Random_Long(lng_Politics_Min_Anger_Flux, lng_Politics_Max_Anger_Flux)
        set anger_amt := 0
        set other_anger_amt := 0

        // Add anger for other political status with the selected player and other players
        for plr_index := 1 to list_count do
          if (list_index <> plr_index) and (plr_index <> sys_long_Player_ID) then
            set is_other_known := Sys_Empire_Politics_Is_Player_Known(sys_long_Player_ID, plr_index)
            set is_other_friend := Sys_Empire_Politics_Is_Player_Ally(sys_long_Player_ID, plr_index)
            set is_other_enemy := Sys_Empire_Politics_Is_Player_Enemy(sys_long_Player_ID, plr_index)
            // Get the selected targeted players relations with the other players
            set pol_status := Sys_Empire_Politics_Get_Status_With_Player(list_index, plr_index)
            set pol_status_time_mod := Sys_Trunc(Sys_Empire_Politics_Get_Status_Time_With_Player(list_index, plr_index) ^ 0.5)
            // Is the other player known?
            if (is_other_known) then
              // Is the other player our friend?
              if (is_other_friend) then
                case pol_status
                  POLITICAL_STATUS_TYPE_KNOWN:
                    set anger_amt := Sys_Divide_Long(lng_Politics_Anger_Amount_Enemy_Of_Friend * pol_status_time_mod, 2)
                  POLITICAL_STATUS_TYPE_TREATY:
                    set anger_amt := lng_Politics_Anger_Amount_Friend_Of_Friend * pol_status_time_mod
                  POLITICAL_STATUS_TYPE_WAR:
                    set anger_amt := lng_Politics_Anger_Amount_Enemy_Of_Friend * pol_status_time_mod
                endcase
              endif
              // Is the other player our enemy?
              if (is_other_enemy) then
                case pol_status
                  POLITICAL_STATUS_TYPE_KNOWN:
                    set anger_amt := Sys_Divide_Long(lng_Politics_Anger_Amount_Enemy_Of_Friend * pol_status_time_mod, 2)
                  POLITICAL_STATUS_TYPE_TREATY:
                    // Add extra anger if the target player has a treaty with our primary enemy or in conflict with a mutual defense agreement
                    if (is_mutual_defense_partner) or (plr_index = lng_Politics_Primary_Enemy) then
                      set anger_amt := lng_Politics_Anger_Amount_Friend_Of_Enemy * pol_status_time_mod * 2
                    else
                      set anger_amt := lng_Politics_Anger_Amount_Friend_Of_Enemy * pol_status_time_mod
                    endif
                  POLITICAL_STATUS_TYPE_WAR:
                    set anger_amt := lng_Politics_Anger_Amount_Enemy_Of_Enemy * pol_status_time_mod
                endcase
              endif
              // Pending
              set anger_amt := Sys_Min_Long(anger_amt, max_anger_amt)
              set anger_amt := Sys_Max_Long(anger_amt, min_anger_amt)
              set other_anger_amt := other_anger_amt + anger_amt
            endif
          endif
        endfor
        // Cap contribution
        set other_anger_amt := Sys_Min_Long(other_anger_amt, max_anger_amt * 2)
        set other_anger_amt := Sys_Max_Long(other_anger_amt, min_anger_amt * 2)
        // Add anger amount to our memory for political status with others
        call Add_Memory_Item(list_index, 0, other_anger_amt, 0, 0, MEMORY_ITEM_TYPE_POLITICAL_STATUS_WITH_OTHERS, 0, TRUE)
      endif
    endfor
  endif

  // Adjust anger towards each alliance based on political status
  set list_count := Sys_Get_Number_Of_Alliances()

  if (list_count > 0) then
    for list_index := 1 to list_count do
      if (list_index <> our_alliance_id) then
        set pol_status := Sys_Empire_Politics_Get_Status_With_Alliance(sys_long_Player_ID, list_index)
        set pol_status_time_mod := Sys_Trunc(Sys_Empire_Politics_Get_Status_Time_With_Alliance(sys_long_Player_ID, list_index) ^ 0.5)
        set friendship_pts := lst_Politics_Friendship_Towards_Alliance.get(list_index)
        set anger_amt := 0
        set min_anger_amt := lng_Politics_Min_Anger_For_Political_Status + Sys_Get_Random_Long(lng_Politics_Min_Anger_Flux, lng_Politics_Max_Anger_Flux)
        set max_anger_amt := lng_Politics_Max_Anger_For_Political_Status + Sys_Get_Random_Long(lng_Politics_Min_Anger_Flux, lng_Politics_Max_Anger_Flux)
        // Adjust our anger amount for the selected alliance based on our current political status
        case pol_status
          POLITICAL_STATUS_TYPE_KNOWN:
            set anger_amt := lng_Politics_Anger_Amount_For_Known_Status_Time * pol_status_time_mod
          POLITICAL_STATUS_TYPE_TREATY:
            if (friendship_pts > lng_Politics_Max_Friendship_Pts_For_Anger) then
              set anger_amt := lng_Politics_Anger_Amount_For_Treaty_Status_Time * pol_status_time_mod
            else
              set anger_amt := Sys_Divide_Long(lng_Politics_Anger_Amount_For_Treaty_Status_Time * pol_status_time_mod, 2)
            endif
          POLITICAL_STATUS_TYPE_WAR:
            set anger_amt := lng_Politics_Anger_Amount_For_War_Status_Time * pol_status_time_mod
        endcase
        // Anger
        set anger_amt := Sys_Min_Long(anger_amt, max_anger_amt)
        set anger_amt := Sys_Max_Long(anger_amt, min_anger_amt)
        // Add the anger amount to our memory
        call Add_Memory_Item(0, list_index, anger_amt, 0, 0, MEMORY_ITEM_TYPE_POLITICAL_STATUS, pol_status, TRUE)
      endif
    endfor
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Add_Anger_For_Locations
//------------------------------------------------------------------------
function Add_Anger_For_Locations returns boolean
vars
  num_players:               long
  list_count:                long
  list_index:                long
  plr_index:                 long
  friendship_pts:            long
  target_priority:           long
  target_count:              long
  target_id:                 long
  ship_count:                long
  unit_count:                long
  colony_count:              long
  anger_amt:                 long
begin

  // Get the number of players
  set num_players := Sys_Get_Number_Of_Players()

  if (num_players > 0) then
    for plr_index := 1 to num_players do
      if (plr_index <> sys_long_Player_ID) then
        set anger_amt := 0
        set target_priority := lst_Politics_Target_Player_Priority.get(plr_index)
        set friendship_pts := lst_Politics_Friendship_Towards_Player.get(plr_index)
        set ship_count := lst_AI_Anger_Location_Ship_Count.get(plr_index)
        set unit_count := lst_AI_Anger_Location_Unit_Count.get(plr_index)
        set colony_count := lst_AI_Anger_Location_Colony_Count.get(plr_index)
        // Adjust modifier based on type of player
        if (not Sys_Are_We_Computer_Player(plr_index)) then
          set ship_count := Sys_Trunc(ship_count * 1.5)
          set unit_count := Sys_Trunc(unit_count * 2.0)
          set colony_count := Sys_Trunc(colony_count * 2.0)
        endif
        // Add anger for enemy and non-friendly empire ships and colonies
        if (friendship_pts < lng_Politics_Max_Friendship_Pts_For_Anger) or ((sys_long_Player_ID = 4) and (plr_index = 2)) then
          // Adjust anger based on target priority
          if (target_priority < TARGET_PRIORITY_HIGH) or (lst_Politics_Non_Aggression_Level.get(plr_index) > NON_AGGRESSION_NEUTRAL) then
            set ship_count := Sys_Trunc(ship_count ^ 0.5)
            set unit_count := Sys_Trunc(unit_count ^ 0.5)
            set colony_count := Sys_Trunc(colony_count ^ 0.5)
          else
            set ship_count := Sys_Trunc(ship_count ^ 0.66)
            set unit_count := Sys_Trunc(unit_count ^ 0.66)
            set colony_count := Sys_Trunc(colony_count ^ 0.66)
          endif
          // Calculate the anger amount
          set anger_amt := ship_count * lng_AI_Anger_Amount_Ships_In_Territory
          set anger_amt := anger_amt + (unit_count * lng_AI_Anger_Amount_Colonies_In_Territory)
          set anger_amt := anger_amt + (colony_count * lng_AI_Anger_Amount_Colonies_In_Territory)
        else
          // Still be lightly upset about unit groups even if we're good friends
          set unit_count := Sys_Trunc(unit_count ^ 0.5)
          set anger_amt := anger_amt + (unit_count * lng_AI_Anger_Amount_Units_In_Territory)
        endif
      endif
      // Add the anger amount to our memory
      call Add_Memory_Item(plr_index, 0, anger_amt, 0, 0, MEMORY_ITEM_TYPE_SHIPS_IN_TERRITORY, 0, TRUE)
    endfor
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Calculate_Current_Anger
//------------------------------------------------------------------------
function Calculate_Current_Anger returns boolean
vars
  list_count:          long
  list_index:          long
  final_anger:         long
  min_anger:           long := 999999
  plr_index:           long
  our_alliance_id:     long
begin

  // Are we in an alliance?
  set our_alliance_id := Sys_Empire_Politics_In_Alliance_ID(sys_long_Player_ID)

  // Calculate our anger towards other players
  set list_count := Sys_Get_Number_Of_Players()

  if (list_count > 0) then
    for list_index := 1 to list_count do
      set final_anger := 0
      if (sys_long_Player_ID <> list_index) and Sys_Empire_Politics_Is_Player_Known(sys_long_Player_ID, list_index) then
        if (Sys_Empire_Politics_In_Alliance_ID(list_index) = 0) then
          set final_anger := Calculate_Current_Anger_For_Entity(list_index, 0)
          // Determine our friendliest relation
          if (final_anger < min_anger) then
            set min_anger := final_anger
            set plr_index := list_index
          endif
        endif
      endif
      call lst_Politics_Anger_Towards_Player.add(final_anger)
    endfor
  endif

  // Note our friendliest relation
  set lng_Politics_Primary_Friend := plr_index

  // Calculate our anger towards alliances
  set list_count := Sys_Get_Number_Of_Alliances()

  if (list_count > 0) then
    for list_index := 1 to list_count do
      set final_anger := 0
      if (list_index <> our_alliance_id) and Sys_Empire_Politics_Is_Alliance_Known(list_index, sys_long_Player_ID) then
        set final_anger := Calculate_Current_Anger_For_Entity(0, list_index)
      endif
      call lst_Politics_Anger_Towards_Alliance.add(final_anger)
    endfor
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Calculate_Current_Anger_For_Entity
//------------------------------------------------------------------------
function Calculate_Current_Anger_For_Entity returns long
params
  plr_id:                    long
  alliance_id:               long
vars
  memory_count:              long
  memory_index:              long
  pol_status:                long
  anger_amt:                 long
  anger_mod:                 long
  total_anger_amt:           long
  final_anger:               long
  fear_towards_plr:          long
  target_priority:           long
  their_primary_enemy:       long
  their_primary_friend:      long
  mood_descr:                string
  debug_str:                 string
begin

  // Get the number of items in our political memory
  set memory_count := lst_Politics_Memory_Player.count()

  // Set our base anger amount
  set total_anger_amt := lng_Politics_Base_Anger_Level

  // Get our fear and priority levels versus the selected player
  if (plr_id > 0) then
    set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(plr_id)
    set target_priority := lst_Politics_Target_Player_Priority.get(plr_id)
    set pol_status := Sys_Empire_Politics_Get_Status_With_Player(sys_long_Player_ID, plr_id)
  else
    set fear_towards_plr := lst_Politics_Fear_Towards_Alliance.get(alliance_id)
    set target_priority := lst_Politics_Target_Alliance_Priority.get(alliance_id)
    set pol_status := Sys_Empire_Politics_Get_Status_With_Alliance(sys_long_Player_ID, alliance_id)
  endif

  // Debug output
  case pol_status
    POLITICAL_STATUS_TYPE_KNOWN:
      set debug_str := " (Known):"
    POLITICAL_STATUS_TYPE_TREATY:
      set debug_str := " (" + Sys_Empire_Politics_Get_Treaty_Name_Between_Players(sys_long_Player_ID, plr_id) + "):"
    POLITICAL_STATUS_TYPE_WAR:
      set debug_str := " (War):"
  endcase

  // Add up all our anger amounts for the selected player
  if (pol_status > POLITICAL_STATUS_TYPE_UNKNOWN) then
    call Sys_Debug_Print("Politics", "------")
    call Sys_Debug_Print("Politics", "  Anger elements for " + Sys_Empire_Get_Empire_Name(plr_id) + debug_str)
    call Sys_Debug_Print("Politics", "    - Base Anger = " + Sys_Convert_Long_To_String(lng_Politics_Base_Anger_Level))
    // Look through our memories for this player
    if (memory_count > 0) then
      for memory_index := 1 to memory_count do
        set anger_amt := 0
        if ((plr_id > 0) and (lst_Politics_Memory_Player.get(memory_index) = plr_id)) or ((alliance_id > 0) and (lst_Politics_Memory_Alliance.get(memory_index) = alliance_id)) then
          // Is this an anger event?
          if (lst_Politics_Memory_Anger_Amount.get(memory_index) <> 0) then
            set anger_amt := lst_Politics_Memory_Anger_Amount.get(memory_index)
          endif
          // Add to our total anger
          set total_anger_amt := total_anger_amt + anger_amt
          // Debug output
          set debug_str := "Date = " + Sys_Convert_Long_To_Date_String(lst_Politics_Memory_Date.get(memory_index))
          set debug_str := debug_str + "; Anger = " + Sys_Convert_Long_To_String(anger_amt)
          set debug_str := debug_str + "; Entry Type = " + Get_Memory_Type_Name(lst_Politics_Memory_Entry_Type.get(memory_index))
          set debug_str := debug_str + "; Entry Value = " + Get_Memory_Entry_Value_Name(lst_Politics_Memory_Entry_Type.get(memory_index), lst_Politics_Memory_Entry_Value.get(memory_index))
          call Sys_Debug_Print("Politics", "  - " + debug_str)
        endif
      endfor
    endif
  endif

  // Add or subtract anger for similarity in government/society types
  if (Compatible_Government_Types(plr_id) < 1) then
    set anger_mod := anger_mod + lng_Politics_Anger_Reduction_For_Similarity
    // Debug output
    call Sys_Debug_Print("Politics", "    - Similar government; Anger = " + Sys_Convert_Long_To_String(lng_Politics_Anger_Reduction_For_Similarity))
  else
    set anger_mod := anger_mod + lng_Politics_Anger_Increase_For_Dissimilarity
    // Debug output
    call Sys_Debug_Print("Politics", "    - Dissimilar government; Anger = " + Sys_Convert_Long_To_String(lng_Politics_Anger_Increase_For_Dissimilarity))
  endif
  if (Compatible_Society_Types(plr_id) < 1) then
    set anger_mod := anger_mod + lng_Politics_Anger_Reduction_For_Similarity
    // Debug output
    call Sys_Debug_Print("Politics", "    - Similar society; Anger = " + Sys_Convert_Long_To_String(lng_Politics_Anger_Reduction_For_Similarity))
  else
    set anger_mod := anger_mod + lng_Politics_Anger_Increase_For_Dissimilarity
    // Debug output
    call Sys_Debug_Print("Politics", "    - Dissimilar society; Anger = " + Sys_Convert_Long_To_String(lng_Politics_Anger_Increase_For_Dissimilarity))
  endif

  // If we are at war, reduce anger versus lower priority players
  if (lng_AI_Num_Of_Wars > 0) then
    if (lng_Politics_Primary_Enemy <> plr_id) then
      if (target_priority < TARGET_PRIORITY_HIGH) then
        // Reduce anger more for reduced priority players
        set anger_mod := anger_mod + (lng_Politics_Anger_Reduction_For_Wars * lng_AI_Num_Of_Wars)
        // Debug output
        call Sys_Debug_Print("Politics", "    - Reduction for war low priority; Anger = " + Sys_Convert_Long_To_String(lng_Politics_Anger_Reduction_For_Wars * lng_AI_Num_Of_Wars))
      else
        set anger_mod := anger_mod + Sys_Divide_Long(lng_Politics_Anger_Reduction_For_Wars * lng_AI_Num_Of_Wars, 2)
        // Debug output
        call Sys_Debug_Print("Politics", "    - Reduction for war high priority; Anger = " + Sys_Convert_Long_To_String(Sys_Divide_Long(lng_Politics_Anger_Reduction_For_Wars * lng_AI_Num_Of_Wars, 2)))
      endif
    endif
  endif

  // Reduce our anger for players who have the same common primary enemy
  set their_primary_enemy := Sys_Get_AI_Storage_Long(plr_id, 1, 3)
  set their_primary_friend := Sys_Get_AI_Storage_Long(plr_id, 1, 4)

  if (their_primary_enemy > 0) and (lng_Politics_Primary_Enemy = their_primary_enemy) then
    set anger_mod := anger_mod + lng_Politics_Anger_Reduction_For_Common_Enemy
    // Debug output
    call Sys_Debug_Print("Politics", "    - Common primary enemy; Anger = " + Sys_Convert_Long_To_String(lng_Politics_Anger_Reduction_For_Common_Enemy))
  endif

  if (their_primary_friend > 0) and (lng_Politics_Primary_Enemy = their_primary_friend) then
    set anger_mod := anger_mod - lng_Politics_Anger_Reduction_For_Common_Enemy
    // Debug output
    call Sys_Debug_Print("Politics", "    - Friends with primary enemy; Anger = " + Sys_Convert_Long_To_String(-lng_Politics_Anger_Reduction_For_Common_Enemy))
  endif

  // Increase our anger for the mega evil player
  if (bool_Mega_Evil_Activated) then
    if Sys_Empire_Politics_Is_Player_The_Ultimate_Evil(sys_long_Player_ID, plr_id) then
      set anger_mod := anger_mod + lng_Politics_Anger_Increase_For_Mega_Evil
      // Debug output
      call Sys_Debug_Print("Politics", "    - Mega Evil player; Anger = " + Sys_Convert_Long_To_String(lng_Politics_Anger_Increase_For_Mega_Evil))
    else
      // Reduce our anger versus other non-mega evil players
      if (pol_status = POLITICAL_STATUS_TYPE_WAR) then
        set anger_mod := anger_mod + (lng_Politics_Anger_Reduction_For_Mega_Evil * 2)
        // Debug output
        call Sys_Debug_Print("Politics", "    - Not Mega Evil player but at war with; Anger = " + Sys_Convert_Long_To_String(lng_Politics_Anger_Reduction_For_Mega_Evil * 2))
      else
        set anger_mod := anger_mod + (lng_Politics_Anger_Reduction_For_Mega_Evil)
        // Debug output
        call Sys_Debug_Print("Politics", "    - Not Mega Evil player; Anger = " + Sys_Convert_Long_To_String(lng_Politics_Anger_Reduction_For_Mega_Evil))
      endif
    endif
  endif

  // Reduce our anger for AI players when AI team mode is on
  if (bool_AI_Team_Mode_On) and (not Sys_Empire_Politics_Is_Player_On_Our_Team(sys_long_Player_ID, plr_id)) then
    set anger_mod := anger_mod + lng_Politics_Anger_Reduction_For_AI_Team
    // Debug output
    call Sys_Debug_Print("Politics", "    - Evil humans; Anger = " + Sys_Convert_Long_To_String(lng_Politics_Anger_Reduction_For_AI_Team))
  endif

  // Reduce our anger for AI rivals of strong human players
  if (bool_Human_Empire_Is_Strong) then
    // Reduce our anger against other strong AI players when human players are strong
    if (Sys_Are_We_Computer_Player(plr_id)) then
      if (lng_Politics_State_Modifier < fear_towards_plr) then
        set anger_mod := anger_mod + (target_priority * -3)
        // Debug output
        call Sys_Debug_Print("Politics", "    - AI rival of strong human player; Anger = " + Sys_Convert_Long_To_String(target_priority * -3))
      endif
    else
      // Reduce our anger against another strong human player if they are at war with our primary enemy
      if (not Sys_Are_We_Computer_Player(lng_Combat_Primary_Enemy)) or (not Sys_Are_We_Computer_Player(lng_Combat_Primary_Enemy)) then
        if (Sys_Empire_Politics_At_War_With_Player(plr_id, lng_Politics_Primary_Enemy)) or (Sys_Empire_Politics_At_War_With_Player(plr_id, lng_Politics_Primary_Enemy)) then
          set anger_mod := anger_mod - (target_priority * -5)
          // Debug output
          call Sys_Debug_Print("Politics", "    - Other human rival of strong human player; Anger = " + Sys_Convert_Long_To_String(target_priority * -5))
        endif
      else
        // Increase our anger versus the strong human player if we are a relatively strong empire
        if (lng_Politics_Score_Rank <= 5) and (target_priority > TARGET_PRIORITY_LOW) then
          set anger_mod := anger_mod + (target_priority * 5)
          // Debug output
          call Sys_Debug_Print("Politics", "    - Strong human player; Anger = " + Sys_Convert_Long_To_String(target_priority * 5))
        else
          set anger_mod := anger_mod + (target_priority * 3)
          // Debug output
          call Sys_Debug_Print("Politics", "    - Strong human player; Anger = " + Sys_Convert_Long_To_String(target_priority * 3))
        endif
      endif
    endif
  endif

  // Add anger to stabilize friendly galaxy
  if (lng_AI_Num_Of_Wars = 0) and (not bool_Early_Game) then
    if (lng_Politics_Primary_Enemy = plr_id) then
      if (lng_Politics_State_Modifier <= 0) then
        set anger_mod := anger_mod + lng_Politics_Anger_Increase_For_Friendly_Galaxy
        // Debug output
        call Sys_Debug_Print("Politics", "    - Destabilize friendly galaxy; Anger = " + Sys_Convert_Long_To_String(lng_Politics_Anger_Increase_For_Friendly_Galaxy))
      endif
    endif
  endif

  // Set our final anger amount between 0 and 100
  set final_anger := total_anger_amt + anger_mod

  if (final_anger < 0) then
    set final_anger := 0
  endif
  if (final_anger > 100) then
    set final_anger := 100
  endif

  set final_anger := Sys_Max_Long(lng_Politics_Min_Anger_Allowed, final_anger)

  // Set our mood against the other Empires based on our anger and fear levels
  set mood_descr := "Indifferent"

  if (final_anger <= 10) then
    set mood_descr := "Brotherly"
    if (fear_towards_plr > 20) then
      set mood_descr := "Reverent"
    endif
    if (fear_towards_plr < -20) then
      set mood_descr := "Friendly"
    endif
  endif
  if (final_anger > 10) and (final_anger <= 30) then
    set mood_descr := "Amiable"
    if (fear_towards_plr > 20) then
      set mood_descr := "Pleasing"
    endif
    if (fear_towards_plr < -20) then
      set mood_descr := "Cooperative"
    endif
  endif
  if (final_anger > 30) and (final_anger <= 40) then
    set mood_descr := "Receptive"
    if (fear_towards_plr > 20) then
      set mood_descr := "Accommodating"
    endif
    if (fear_towards_plr < -20) then
      set mood_descr := "Helpful"
    endif
  endif
  if (final_anger > 40) and (final_anger <= 60) then
    set mood_descr := "Indifferent"
    if (fear_towards_plr > 20) then
      set mood_descr := "Compliant"
    endif
    if (fear_towards_plr < -20) then
      set mood_descr := "Apathetic"
    endif
  endif
  if (final_anger > 60) and (final_anger <= 70) then
    set mood_descr := "Displeased"
    if (fear_towards_plr > 20) then
      set mood_descr := "Apprehensive"
    endif
    if (fear_towards_plr < -20) then
      set mood_descr := "Imposing"
    endif
  endif
  if (final_anger > 70) and (final_anger <= 90) then
    set mood_descr := "Angry"
    if (fear_towards_plr > 20) then
      set mood_descr := "Fearful"
    endif
    if (fear_towards_plr < -20) then
      set mood_descr := "Aggressive"
    endif
  endif
  if (final_anger > 90) then
    set mood_descr := "Murderous"
    if (fear_towards_plr > 20) then
      set mood_descr := "Terrified"
    endif
    if (fear_towards_plr < -20) then
      set mood_descr := "Insatiable"
    endif
  endif

  if (plr_id > 0) then
    // Set our mood towards the specified player
    call Sys_Empire_Politics_Set_Mood_Towards_Empire(sys_long_Player_ID, plr_id, mood_descr)
    call Sys_Empire_Politics_Set_Anger_Pct_Towards_Empire(sys_long_Player_ID, plr_id, final_anger)
    // Debug output
    call Sys_Debug_Print("Politics", "    - Final Anger = " + Sys_Convert_Long_To_String(final_anger))
    call Sys_Debug_Print("Politics", "    - Mood = " + mood_descr)
  else
    // Set our mood towards the specified alliance
    call Sys_Empire_Politics_Set_Mood_Towards_Alliance(sys_long_Player_ID, alliance_id, mood_descr)
    call Sys_Empire_Politics_Set_Anger_Pct_Towards_Aliance(sys_long_Player_ID, alliance_id, final_anger)
    // Debug output
    call Sys_Debug_Print("Politics", "    - Final Anger = " + Sys_Convert_Long_To_String(final_anger))
  endif

  return final_anger
end

//------------------------------------------------------------------------
// Reply_To_Messages
//------------------------------------------------------------------------
function Reply_To_Messages returns boolean
vars
  msg_sent:                  boolean
  lst_log_entries:           longlist
  list_count:                long
  list_index:                long
  log_id:                    long
  message_type:              long
  from_plr:                  long
  from_alliance:             long
  msg_text:                  string
begin

  // Reset the number of messages we have sent to other players or alliances
  call lst_Message_Sent_To_Player.fill(Sys_Get_Number_Of_Players(), 0)
  call lst_Message_Sent_To_Alliance.fill(Sys_Get_Number_Of_Alliances(), 0)

  // Note the messages we have received
  call Sys_Empire_Log_Get_Log_Entries_With_Messages_For_This_Turn(sys_long_Player_ID, lst_log_entries)

  // Determine the type of response for each message we received
  set list_count := lst_log_entries.count()
  if (list_count > 0) then
    for list_index := 1 to list_count do
      set log_id := lst_log_entries.get(list_index)
      set message_type := Sys_Empire_Log_Get_Log_Entry_Message_Type(sys_long_Player_ID, log_id)
      set from_plr := Sys_Empire_Log_Get_Log_Entry_Message_From_Player(sys_long_Player_ID, log_id)
      set from_alliance := Sys_Empire_Log_Get_Log_Entry_Message_From_Alliance(sys_long_Player_ID, log_id)
      set msg_sent := FALSE

      // Debug output
      call Sys_Debug_Print("Politics", "------")
      call Sys_Debug_Print("Politics", "  - Message from the " + Sys_Empire_Get_Empire_Name(from_plr) + " (" Get_Message_Type(message_type) + ")")

      case (message_type)
        // POLITICS_MSG_GENERAL_MESSAGE:
        // POLITICS_MSG_REPLY_TO_MESSAGE:
        POLITICS_MSG_DECLARE_WAR:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_SURRENDER:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_GRANT_INDEPENDENCE:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_PROPOSE_TREATY:
          set msg_sent := Reply_To_Propose_Treaty(log_id)
        POLITICS_MSG_PROPOSE_CHANGES_IN_TREATY:
          set msg_sent := Reply_To_Propose_Treaty(log_id)
        POLITICS_MSG_ACCEPT_TREATY:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_ACCEPT_TREATY_CHANGES:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_REFUSE_TREATY:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_REFUSE_TREATY_CHANGES:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_COUNTER_TREATY_PROPOSAL:
          set msg_sent := Reply_To_Propose_Treaty(log_id)
        POLITICS_MSG_COUNTER_TREATY_CHANGES:
          set msg_sent := Reply_To_Propose_Treaty(log_id)
        POLITICS_MSG_BREAK_TREATY:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_PROPOSE_TRADE:
          set msg_sent := Reply_To_Propose_Trade(log_id)
        POLITICS_MSG_ACCEPT_TRADE:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_REFUSE_TRADE:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_COUNTER_TRADE:
          set msg_sent := Reply_To_Propose_Trade(log_id)
        POLITICS_MSG_GIVE_GIFT:
          set msg_sent := Reply_To_Give_Gift(log_id)
        POLITICS_MSG_ACCEPT_GIFT:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_REFUSE_GIFT:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_PROPOSE_NEW_ALLIANCE:
          set msg_sent := Reply_To_Propose_Alliance(log_id)
        POLITICS_MSG_ACCEPT_ALLIANCE:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_REFUSE_ALLIANCE:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_COUNTER_ALLIANCE_PROPOSAL:
          set msg_sent := Reply_To_Propose_Alliance(log_id)
        POLITICS_MSG_BREAK_WITH_ALLIANCE:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_CHANGE_ALLIANCE_RULE:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_ADD_EMPIRE_TO_ALLIANCE:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_REMOVE_EMPIRE_FROM_ALLIANCE:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_PROPOSE_EMPIRE_JOIN_ALLIANCE:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_REQUEST_ACCEPT:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_REQUEST_REFUSE:
          set msg_sent := Reply_To_General_Message(log_id)
        POLITICS_MSG_REQUEST_GIFT:
          set msg_sent := Reply_To_Request_Gift(log_id)
        POLITICS_MSG_REQUEST_SURRENDER:
          set msg_sent := Reply_To_Request_Surrender(log_id)
        POLITICS_MSG_REQUEST_STOP_AGGRESSION_AGAINST_EMPIRE:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_BREAK_TREATY_WITH_EMPIRE:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_DECLARE_WAR_ON_EMPIRE:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_MAKE_PEACE_WITH_EMPIRE:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_TO_JOIN_ALLIANCE:
          set msg_sent := Reply_To_Request_Join_Alliance(log_id)
        POLITICS_MSG_REQUEST_EMPIRE_BREAK_WITH_ALLIANCE:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_EMPIRE_JOIN_WITH_ALLIANCE:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_STOP_ESPIONAGE_AGAINST_US:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_STOP_ESPIONAGE_AGAINST_EMPIRE:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_STOP_SABOTAGE_AGAINST_US:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_STOP_SABOTAGE_AGAINST_EMPIRE:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_STOP_SHIP_ATTACKS_IN_SYSTEM:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_MILITARY_ASSISTANCE:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_MILITARY_ASSISTANCE_AGAINST_EMPIRE:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_MILITARY_ASSISTANCE_IN_SYSTEM:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_ECONOMIC_ASSISTANCE:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_TECHNOLOGICAL_ASSISTANCE:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_INTELLIGENCE_ASSISTANCE:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_INTELLIGENCE_ASSISTANCE_AGAINST_EMPIRE:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_STOP_BORDER_INCURSIONS:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_STOP_MILITARY_ATTACKS_ON_US:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_STOP_MILITARY_ATTACKS_AGAINST_EMPIRE:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_REMOVE_SHIPS_FROM_SYSTEM:
          set msg_sent := Reply_To_General_Request(log_id)
        POLITICS_MSG_REQUEST_REMOVE_COLONIES_FROM_SYSTEM:
          set msg_sent := Reply_To_General_Request(log_id)
      endcase
      // Note if we sent a reply to their message
      if (msg_sent) then
        if (from_plr > 0) then
          call lst_Message_Sent_To_Player.set(from_plr, 1)
        endif
        if (from_alliance > 0) then
          call lst_Message_Sent_To_Alliance.set(from_alliance, 1)
        endif
      endif
    endfor
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Reply_To_Propose_Treaty
//------------------------------------------------------------------------
function Reply_To_Propose_Treaty returns boolean
params
  log_id:                    long
vars
  msg_sent:                  boolean := FALSE
  anger_towards_plr:         long
  fear_towards_plr:          long
  target_priority:           long
  target_priority_mod:       long
  new_log_id:                long
  message_type:              long
  from_plr:                  long
  from_alliance:             long
  from_plr_name:             string
  new_msg_type:              long
  pol_status:                long
  pol_status_time:           long
  last_offer_date:           long
  coop_status:               long
  coop_level:                long
  treaty_change:             boolean := FALSE
  accept_proposal:           boolean := TRUE
  counter_proposal:          boolean := TRUE
  min_elem_anger:            long
  anger_mod:                 long
  proposed_treaty_name:      string
  msg_text:                  string
begin

  // Get the message's parameters
  set message_type := Sys_Empire_Log_Get_Log_Entry_Message_Type(sys_long_Player_ID, log_id)
  set from_plr := Sys_Empire_Log_Get_Log_Entry_Message_From_Player(sys_long_Player_ID, log_id)
  set from_alliance := Sys_Empire_Log_Get_Log_Entry_Message_From_Alliance(sys_long_Player_ID, log_id)
  set proposed_treaty_name := Sys_Empire_Log_Get_Log_Entry_Message_Treaty_Name(sys_long_Player_ID, log_id)

  // Prepare our reply
  set new_log_id := Sys_Empire_Politics_Create_Temporary_Message(sys_long_Player_ID)

  call Sys_Empire_Politics_Set_Message_To_Empire(new_log_id, from_plr)
  call Sys_Empire_Politics_Set_Message_Tone(new_log_id, Get_Message_Tone(from_plr, from_alliance))

  // Reset variables
  set gbl_is_peace_deal := FALSE
  set gbl_accept_treaty := FALSE
  set gbl_treaty_has_non_aggression := FALSE
  set gbl_treaty_has_minefield_codes := FALSE
  set gbl_add_non_aggression := FALSE
  set gbl_add_minefield_codes := FALSE

  // Get our anger, fear, and score levels against the proposing player
  if (from_plr > 0) then
    set from_plr_name := Sys_Empire_Get_Empire_Name(from_plr)
    set anger_towards_plr := lst_Politics_Anger_Towards_Player.get(from_plr)
    set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(from_plr)
    set target_priority := lst_Politics_Target_Player_Priority.get(from_plr)
    set pol_status := Sys_Empire_Politics_Get_Status_With_Player(sys_long_Player_ID, from_plr)
    set pol_status_time := Sys_Empire_Politics_Get_Status_Time_With_Player(sys_long_Player_ID, from_plr)
    set coop_level := lst_Politics_Cooperation_Level.get(from_plr)
  else
    set from_plr_name := Sys_Alliance_Get_Alliance_Name(from_plr)
    set anger_towards_plr := lst_Politics_Anger_Towards_Alliance.get(from_alliance)
    set fear_towards_plr := lst_Politics_Fear_Towards_Alliance.get(from_alliance)
    set target_priority := lst_Politics_Target_Alliance_Priority.get(from_alliance)
  endif

  // Set our target priority modifier
  if (lng_AI_Num_Of_Wars > 1) or (lng_AI_Num_Of_Enemies > 2) then
    set target_priority_mod := TARGET_PRIORITY_HIGH
  else
    set target_priority_mod := TARGET_PRIORITY_MEDIUM
  endif

  // Debug output
  call Sys_Debug_Print("Politics", "    - Current Anger = " + Sys_Convert_Long_To_String(anger_towards_plr) + "; Current Coop Level = " + Sys_Convert_Long_To_String(coop_level))
  call Sys_Debug_Print("Politics", "    - Treaty Name = " + proposed_treaty_name)

  // Modify our existing treaty or a new treaty?
  if (message_type = POLITICS_MSG_PROPOSE_CHANGES_IN_TREATY) then
    set treaty_change := TRUE
  endif

  // Determine the maximum anger level of the treaty's elements
  set min_elem_anger := Compute_Max_Anger_For_Treaty_Elements(log_id, anger_towards_plr, fear_towards_plr, coop_level, treaty_change)

  // Accept the treaty proposal if none of its elements exceed our maximum anger level to accept
  if (accept_proposal) then
    set accept_proposal := (anger_towards_plr <= min_elem_anger + anger_mod)
    // Reject based on anger
    if (not accept_proposal) then
      // Debug output
      call Sys_Debug_Print("Politics", "    - Reject due to Anger")
    endif
  endif

  // Accept the treaty proposal if it does not exceed our maximum anger level to accept treaty
  if (accept_proposal) then
    set accept_proposal := (anger_towards_plr <= lng_Politics_Max_Anger_To_Accept_Treaty + fear_towards_plr)
  endif

  // Should we consider accepting a peace treaty if the player is a low priority target for us?
  if (gbl_is_peace_deal) then
    if (pol_status = POLITICAL_STATUS_TYPE_KNOWN) or (pol_status = POLITICAL_STATUS_TYPE_WAR) or (bool_AI_Strategy_Peaceful) then
      if (target_priority < target_priority_mod) then
        set accept_proposal := TRUE
      endif
    endif
    // Accept a peace deal against a significant rival if we are desperate for peace
    if (bool_AI_Strategy_Seek_Peace) and (fear_towards_plr > target_priority) then
      set accept_proposal := TRUE
    endif
  endif

  // Do not accept a treaty from the mega evil player!
  if Sys_Is_Game_Using_Ultimate_Evil_Player() and Sys_Empire_Politics_Is_Player_The_Ultimate_Evil(sys_long_Player_ID, from_plr) then
    set accept_proposal := FALSE
    set counter_proposal := FALSE
  endif

  // Accept the proposal in AI team mode if we are on the same team
  if Sys_Is_Game_Using_Teams() then
    set accept_proposal := Sys_Empire_Politics_Is_Player_On_Our_Team(sys_long_Player_ID, from_plr)
    set counter_proposal := FALSE
  endif

  // Did we accept the treaty proposal?
  if (accept_proposal) then
    // Accept the proposed treaty or treaty change...
    if (treaty_change) then
      set new_msg_type := POLITICS_MSG_ACCEPT_TREATY_CHANGES
      // Debug output
      call Sys_Debug_Print("Politics", "  - Accepted Changes to Treaty")
    else
      set new_msg_type := POLITICS_MSG_ACCEPT_TREATY
      // Debug output
      call Sys_Debug_Print("Politics", "  - Accepted Treaty")
    endif
    // Copy the treaty proposal to the new log message
    call Sys_Empire_Politics_Copy_Treaty_Proposal(sys_long_Player_ID, log_id, new_log_id)
  else
    // If we don't accept, do we make a counter proposal instead?
    // Do not counter due to too many concessions
    if (min_elem_anger = -100) then
      set counter_proposal := FALSE
      // Debug output
      call Sys_Debug_Print("Politics", "    - Did not counter due to too many concessions")
    endif
    // Is our anger level low enough to consider a counter proposal?
    if (counter_proposal) then
      set counter_proposal := (anger_towards_plr <= (lng_Politics_Max_Anger_To_Counter_Treaty + fear_towards_plr))
      // Debug output
      call Sys_Debug_Print("Politics", "    - Max Anger to counter = " + Sys_Convert_Long_To_String(lng_Politics_Max_Anger_To_Counter_Treaty + fear_towards_plr))
    endif
    // Get the treaty elements to propose in our counter treaty
    if (counter_proposal) then
      set counter_proposal := Compute_Counter_Treaty_Elements(log_id, new_log_id, anger_towards_plr, fear_towards_plr)
    else
      // Debug output
      call Sys_Debug_Print("Politics", "    - Did not counter due to anger")
    endif
    // Counter the proposed changes to treaty or treaty...
    if (counter_proposal) then
      If (treaty_change) then
        set new_msg_type := POLITICS_MSG_COUNTER_TREATY_CHANGES
        // Debug output
        call Sys_Debug_Print("Politics", "    - Countered Changes to Treaty")
      else
        set new_msg_type := POLITICS_MSG_COUNTER_TREATY_PROPOSAL
        // Debug output
        call Sys_Debug_Print("Politics", "    - Countered Treaty")
      endif
    else
      // Special flag when the counter proposal is the same as the original proposal
      if (gbl_accept_treaty) then
        // If the counter proposal was the same as the original proposal, just accept the treaty as is
        set new_msg_type := POLITICS_MSG_ACCEPT_TREATY
        call Sys_Empire_Politics_Copy_Treaty_Proposal(sys_long_Player_ID, log_id, new_log_id)
      else
        // Refuse the treaty proposal
        set new_msg_type := POLITICS_MSG_REFUSE_TREATY
        // Debug output
        call Sys_Debug_Print("Politics", "    - Rejected Treaty")
        // Special message
        if (str_Reject_Reason <> "") then
          set str_Reject_Reason := "Reject Treaty Too Angry"
        endif
        // Mix up the special message from time to time if we are at war
        if (pol_status = POLITICAL_STATUS_TYPE_WAR) and (Sys_Get_Random_Long(1, 2) = 1) then
          set str_Reject_Reason := "Reject Treaty Due To War"
        endif
      endif
    endif
  endif

  // Is it too soon to make a treaty revision?
  if (pol_status = POLITICAL_STATUS_TYPE_TREATY) and (pol_status_time < lng_Politics_Min_Time_To_Accept_Treaty_Change) then
    set new_msg_type := POLITICS_MSG_REFUSE_TREATY_CHANGES
    // Debug output
    call Sys_Debug_Print("Politics", "  - Rejected as its too soon since our last one")
    // Special message
    if (Sys_Get_Random_Long(1, 2) = 1) then
      set str_Reject_Reason := "Reject Treaty Too Soon"
    endif
  endif

  // Has this player broken treaties too much?
  if (lst_Num_Times_Treaty_Broken.get(from_plr) > 0) and (not treaty_change) then
    // The more they've broken a treaty, the less likely we'll accept
    if (Sys_Get_Random_Long(1, 3) < lst_Num_Times_Treaty_Broken.get(from_plr)) then
      set new_msg_type := POLITICS_MSG_REFUSE_TREATY
      set str_Reject_Reason := "Reject Treaty Break Too Often"
      // Debug output
      call Sys_Debug_Print("Politics", "  - Rejected as the player breaks treaties too much")
    endif
  endif

  // Send our response
  if (new_msg_type > 0) then
    set msg_text := Get_Message_Text(new_msg_type, message_type, from_plr, from_alliance, 0, 0, proposed_treaty_name, "", 0, 0)
    // Send the message
    if (Sys_Length_String(msg_text) > 0) then
      call Sys_Empire_Politics_Set_Message_Type(new_log_id, new_msg_type)
      call Sys_Empire_Politics_Set_Message_Text(new_log_id, msg_text)
      set msg_sent := Sys_Empire_Politics_Send_Message(new_log_id)
      call Sys_Debug_Print("Politics", "    - Message Text = " + msg_text)
    endif
  endif

  return msg_sent
end

//------------------------------------------------------------------------
// Compute_Counter_Treaty_Elements
//------------------------------------------------------------------------
function Compute_Counter_Treaty_Elements returns boolean
params
  log_id:                    long
  new_log_id:                long
  anger_towards_plr:         long
  fear_towards_plr:          long
vars
  from_plr:                  long
  list_count:                long
  list_index:                long
  is_entity_A:               boolean := TRUE
  entity_type_A:             long
  entity_id_A:               long
  entity_A_name:             string
  entity_type_B:             long
  entity_id_B:               long
  entity_B_name:             string
  lst_elem_type:             longlist
  lst_elem_value:            longlist
  elem_type:                 long
  elem_value:                long
  new_elem_value:            long
  elem_details:              string
  treaty_name:               string
  proposal_different:        boolean := FALSE
  proposal_ok:               boolean := FALSE
begin

  // Get the treaty's parameters
  call Sys_Empire_Log_Get_Log_Entry_Message_Treaty_Participants(sys_long_Player_ID, log_id, entity_type_A, entity_id_A, entity_type_B, entity_id_B)
  call Sys_Empire_Log_Get_Log_Entry_Message_Treaty_Elements(sys_long_Player_ID, log_id, lst_elem_type, lst_elem_value)
  set treaty_name := Sys_Empire_Log_Get_Log_Entry_Message_Treaty_Name(sys_long_Player_ID, log_id)

  // Are we entity A or B?
  if (entity_id_B = sys_long_Player_ID) then
    set is_entity_A := FALSE
    set from_plr := entity_id_A
    set entity_A_name := Sys_Empire_Get_Empire_Name(from_plr)
    set entity_B_name :=  Sys_Empire_Get_Empire_Name(sys_long_Player_ID)
  else
    set from_plr := entity_id_B
    set entity_A_name :=  Sys_Empire_Get_Empire_Name(sys_long_Player_ID)
    set entity_B_name := Sys_Empire_Get_Empire_Name(from_plr)
  endif

  // Debug output
  call Sys_Debug_Print("Politics", "    - Made a counter offer:")

 // Choose counter treaty elements that we'd prefer
  set list_count := lst_elem_type.count()

  if (list_count > 0) then
    for list_index := 1 to list_count do
      set elem_type := lst_elem_type.get(list_index)
      set elem_value := lst_elem_value.get(list_index)
      // See if there is a better element for us
      set new_elem_value := Get_Specific_Treaty_Element(from_plr, 0, elem_type, is_entity_A)
      // Is this a different element value then before?
      if (elem_value <> new_elem_value) then
        set proposal_different := TRUE
        call lst_elem_value.set(list_index, new_elem_value)
        // Provide a potential reason that we countered
        if (str_Counter_Reason = "") then
          case elem_type
            TREATY_ELEMENT_TYPE_TRADE_PERCENT:
              if (Sys_Get_Random_Long(1, 3) = 1) then
                set str_Counter_Reason := "Changed Trade"
              endif
            TREATY_ELEMENT_TYPE_NON_AGGRESSION:
              case new_elem_value
                1:
                  set str_Counter_Reason := "Changed Non-Aggression Neutral"
                2:
                  set str_Counter_Reason := "Changed Non-Aggression All Systems"
                3:
                  set str_Counter_Reason := "Changed Non-Aggression Allow Colonization"
              endcase
            TREATY_ELEMENT_TYPE_ALLOW_MIGRATION_BETWEEN_COLONIES:
              set str_Counter_Reason := "Changed Migration"
            TREATY_ELEMENT_TYPE_SHARE_TECHNOLOGY:
              set str_Counter_Reason := "Changed Share Technology"
          endcase
        endif
      endif
    endfor
  endif

  // Remove elements from the treaty we don't think are useful
  set list_index := 0

  loop
    set list_index := list_index + 1
    set elem_type := lst_elem_type.get(list_index)
    set elem_value := lst_elem_type.get(list_index)
    // Check to see if the specific element is useful
    if (not Is_Treaty_Element_Useful(from_plr, elem_type, elem_value)) then
      call lst_elem_value.set(list_index, 0)
      // Debug output
      set elem_details := Get_Treaty_Element_Type_Details(elem_type, elem_value, entity_id_A, entity_id_B)
      call Sys_Debug_Print("Politics", "      - Removed " + elem_details + "; " + str_Counter_Reason)
    endif
    // Remove the element if it's not useful
    if (lst_elem_value.get(list_index) = 0) then
      call lst_elem_type.delete(list_index)
      call lst_elem_value.delete(list_index)
      set list_index := list_index - 1
      set list_count := list_count - 1
      // Give possible reasons why we countered...
      if (str_Counter_Reason = "") then
        case elem_type
          TREATY_ELEMENT_TYPE_MUTUAL_DEFENSE_PACT:
            set str_Counter_Reason := "Not Interested Mutual Defense"
          TREATY_ELEMENT_TYPE_ALLOW_MIGRATION_BETWEEN_COLONIES:
            set str_Counter_Reason := "Not Interested Migration"
          TREATY_ELEMENT_TYPE_SHARE_TECHNOLOGY:
            set str_Counter_Reason := "Not Interested Sharing Technology"
          TREATY_ELEMENT_TYPE_SHARE_RESUPPLY:
            set str_Counter_Reason := "Not Useful Sharing Supply"
          TREATY_ELEMENT_TYPE_SHARE_REPAIR:
            set str_Counter_Reason := "Not Useful Sharing Repair"
          TREATY_ELEMENT_TYPE_SHARE_SYSTEM_MAPS:
            set str_Counter_Reason := "Not Useful Sharing Maps"
          TREATY_ELEMENT_TYPE_SHARE_COMMUNICATION_CHANNELS:
            set str_Counter_Reason := "Not Useful Sharing Comms"
          TREATY_ELEMENT_TYPE_SHARE_ESPIONAGE_INFO:
            set str_Counter_Reason := "Not Useful Sharing Espionage"
          TREATY_ELEMENT_TYPE_SHARE_SENSOR_INFO:
            set str_Counter_Reason := "Not Useful Sharing Sensors"
          TREATY_ELEMENT_TYPE_SHARE_DESIGNS:
            set str_Counter_Reason := "Not Useful Sharing Designs"
          TREATY_ELEMENT_TYPE_SHARE_CODES_FOR_MINEFIELDS:
            set str_Counter_Reason := "Not Useful Sharing Minefield Codes"
        endcase
      endif
    endif
    exitwhen (list_index >= list_count) or (list_count = 0)
  endloop

  // Are there missing elements that are mandatory to add?
  // A basic non-aggression element is necessary for every treaty for a computer player
  if (gbl_add_non_aggression) then
    call lst_elem_type.add(TREATY_ELEMENT_TYPE_NON_AGGRESSION)
    // Pick 1 of the 2 element options based on anger
    if (anger_towards_plr > 60) then
      // Neutral systems
      call lst_elem_value.add(1)
    else
      // All systems
      call lst_elem_value.add(2)
    endif
    set str_Counter_Reason := "Guarantee Non-Aggression"
    // Temp Debug output
    call Sys_Debug_Print("Politics", "      - Forced Non-Aggression")
  endif
  // Add sharing minefield codes if we are aware of mines from this player
  if (gbl_add_minefield_codes) then
    call lst_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_CODES_FOR_MINEFIELDS)
    // Share both ways
    call lst_elem_value.add(3)
    set str_Counter_Reason := "Guarantee Minefield Codes"
    // Temp Debug output
    call Sys_Debug_Print("Politics", "      - Forced Minefield Codes")
  endif

  // Debug output
  set list_count := lst_elem_type.count()

  for list_index := 1 to list_count do
    set elem_type := lst_elem_type.get(list_index)
    set elem_value := lst_elem_value.get(list_index)
    // Get the element details and empires involved
    set elem_details := Get_Treaty_Element_Type_Details(elem_type, elem_value, entity_id_A, entity_id_B)
    // Debug output
    call Sys_Debug_Print("Politics", "      - " + elem_details)
  endfor

  // Are there still elements to send in our counter-proposal?
  if (list_count > 0) and (proposal_different) then
    set proposal_ok := TRUE
    // Debug output
    call Sys_Debug_Print("Politics", "      - Stated reason to counter = " + str_Counter_Reason)
  endif

  if (list_count > 0) and (not proposal_different) then
    // Debug output
    call Sys_Debug_Print("Politics", "      - Counter proposal is the same. Accept the treaty.")
    set gbl_accept_treaty := TRUE
  endif

  // Send our counter proposal
  if (proposal_ok) then
    call Sys_Empire_Log_Set_Log_Entry_Message_Treaty_Participants(sys_long_Player_ID, new_log_id, entity_type_A, entity_id_A, entity_type_B, entity_id_B)
    call Sys_Empire_Log_Set_Log_Entry_Message_Treaty_Elements(new_log_id, lst_elem_type, lst_elem_value)
    call Sys_Empire_Log_Set_Log_Entry_Message_Treaty_Name(new_log_id, treaty_name)
  endif

  return proposal_ok
end

//------------------------------------------------------------------------
// Compute_Max_Anger_For_Treaty_Elements
//------------------------------------------------------------------------
function Compute_Max_Anger_For_Treaty_Elements returns long
params
  log_id:                    long
  anger_towards_plr:         long
  fear_towards_plr:          long
  coop_level:                long
  treaty_change:             boolean
vars
  list_count:                long
  list_index:                long
  entity_type_A:             long
  entity_id_A:               long
  entity_A_name:             string
  entity_type_B:             long
  entity_id_B:               long
  entity_B_name:             string
  is_entity_A:               boolean := TRUE
  from_plr:                  long
  lst_elem_type:             longlist
  lst_elem_value:            longlist
  elem_details:              string
  elem_type:                 long
  elem_value:                long
  elem_anger:                long
  elem_anger_flux:           long
  min_elem_anger:            long := 100
  max_elem_count:            long
  elem_concession_value:     long
  treaty_concession_pts:     long
  target_concession_pts:     long
  target_concession_mod:     long
  concession_diff:           long
  counter_concession_max:    long
  start_pos:                 long
  elem_value_found:          boolean := FALSE
  skip_concession_check:     boolean := FALSE
begin

  // Get the treaty's participants and elements
  call Sys_Empire_Log_Get_Log_Entry_Message_Treaty_Participants(sys_long_Player_ID, log_id, entity_type_A, entity_id_A, entity_type_B, entity_id_B)
  call Sys_Empire_Log_Get_Log_Entry_Message_Treaty_Elements(sys_long_Player_ID, log_id, lst_elem_type, lst_elem_value)

  // Are we entity A or B?
  if (entity_id_B = sys_long_Player_ID) then
    set is_entity_A := FALSE
    set from_plr := entity_id_A
    set entity_A_name := Sys_Empire_Get_Empire_Name(from_plr)
    set entity_B_name :=  Sys_Empire_Get_Empire_Name(sys_long_Player_ID)
  else
    set from_plr := entity_id_B
    set entity_A_name :=  Sys_Empire_Get_Empire_Name(sys_long_Player_ID)
    set entity_B_name := Sys_Empire_Get_Empire_Name(from_plr)
  endif

  // Set our target number of concession points (fear divided by 5) and the target concession modifier for flexibility
  set target_concession_pts := Sys_Divide_Long(fear_towards_plr, 5)
  set target_concession_mod := 1 + Sys_Divide_Long(target_concession_pts, 5)
  set counter_concession_max := target_concession_mod + 1

  // Reset peace treaty variable
  set gbl_is_peace_deal := FALSE

  // Go through the proposed treaty elements and calculate the maximum allowed anger for us to accept the proposed treaty
  // Keep track of the value of our concessions for and against
  set list_count := lst_elem_type.count()

  if (list_count > 0) then
    // Debug output
    call Sys_Debug_Print("Politics", "    - Treaty Details:")

    for list_index := 1 to list_count do
      set elem_type := lst_elem_type.get(list_index)
      set elem_value := lst_elem_value.get(list_index)
      set elem_value_found := FALSE
      set start_pos := lng_Politics_Treaty_Elements_Allowed_Type.indexof(elem_type)
      set max_elem_count := lng_Politics_Treaty_Elements_Allowed_Value.count()

      // Skip concession check for treaties that may be simple Non-Aggression or Non-Intercourse treaties
      if (elem_type = TREATY_ELEMENT_TYPE_NON_AGGRESSION) then
        set skip_concession_check := TRUE
      else
        // Expectation is that a peace deal might involve tribute
        if (elem_type = TREATY_ELEMENT_TYPE_RESOURCE_TARIFF) or (elem_type = TREATY_ELEMENT_TYPE_SHARE_SYSTEM_MAPS) then
          // Nothing
        else
          set skip_concession_check := FALSE
        endif
      endif

      // Get the element details and empires involved
      set elem_details := Get_Treaty_Element_Type_Details(elem_type, elem_value, entity_id_A, entity_id_B)
      // Debug output
      call Sys_Debug_Print("Politics", "      - " + elem_details)

      // Is this treaty element useful to us?
      if (not Is_Treaty_Element_Useful(from_plr, elem_type, elem_value)) then
        // Debug output
        call Sys_Debug_Print("Politics", "        - Not a useful element")
      else
        // Nothing
      endif

      if (start_pos > 0) then
        // Find the corresponding anger and concession for each treaty element value
        loop
          if (lng_Politics_Treaty_Elements_Allowed_Value.get(start_pos) = elem_value) then
            set elem_value_found := TRUE
            set elem_anger_flux := Sys_Get_Random_Long(1, 5)
            set elem_anger := lng_Politics_Treaty_Elements_Allowed_Max_Anger.get(start_pos) + elem_anger_flux + fear_towards_plr
            set elem_concession_value := lng_Politics_Treaty_Elements_Allowed_Concession_Value.get(start_pos)
            // Debug output
            call Sys_Debug_Print("Politics", "        - Max allowed element anger = " + Sys_Convert_Long_To_String(elem_anger))
            // Get the number of concession points to add for the treaty element
            if (elem_concession_value > 0) or (elem_concession_value < 0) then
              if (is_entity_A) then
                set treaty_concession_pts := treaty_concession_pts + elem_concession_value
                // Debug output
                call Sys_Debug_Print("Politics", "        - Concession pts = " + Sys_Convert_Long_To_String(elem_concession_value))
              else
                // Flip the anger and concession value if we are entity B
                set treaty_concession_pts := treaty_concession_pts - elem_concession_value
                set elem_anger := 100 - elem_anger
                // Debug output
                call Sys_Debug_Print("Politics", "        - Concession pts = " + Sys_Convert_Long_To_String(-elem_concession_value))
              endif
            endif
            // Note the element value with the lowest allowed anger
            set elem_anger := Sys_Min_Long(elem_anger, 100)
            set elem_anger := Sys_Max_Long(elem_anger, 0)
            // Identify the highest allowed anger
            if (elem_anger < min_elem_anger) then
              set min_elem_anger := elem_anger
            endif
          endif
          set start_pos := start_pos + 1
          exitwhen (elem_value_found) or (start_pos > max_elem_count)
        endloop
      endif
    endfor
  endif

  // Debug output
  call Sys_Debug_Print("Politics", "      - Max Anger for Treaty = " + Sys_Convert_Long_To_String(min_elem_anger))
  call Sys_Debug_Print("Politics", "      - Treaty Concession Pts/Target Concession Pts = " + Sys_Convert_Long_To_String(treaty_concession_pts) + "/" + Sys_Convert_Long_To_String(target_concession_pts))

  // Do not accept the treaty if our concessions are more than our fear level allows
  if (not skip_concession_check) then
    // Was the treaty missing a key basic element for us?
    // Non-Aggression
    if (not gbl_treaty_has_non_aggression) then
      // Trigger counter proposal
      set min_elem_anger := -50
      set gbl_add_non_aggression := TRUE
      // Debug output
      call Sys_Debug_Print("Politics", "        - Did not have a non-aggression element")
    endif
    // Minefield Codes
    if (not gbl_treaty_has_minefield_codes) then
      if Is_Treaty_Element_Useful(from_plr, TREATY_ELEMENT_TYPE_SHARE_CODES_FOR_MINEFIELDS, 3) and (lst_AI_Enemy_Marked_Minefield_Count.get(from_plr) > 0) then
        // Trigger counter proposal
        set min_elem_anger := -50
        set gbl_add_minefield_codes := TRUE
        // Debug output
        call Sys_Debug_Print("Politics", "        - Did not have sharing of minefield codes")
      endif
    endif
    // Does the treaty have the required number of concessions we are willing to accept?
    if (treaty_concession_pts > (target_concession_pts + target_concession_mod)) then
      // How close to the limit is the difference?
      set concession_diff := treaty_concession_pts - (target_concession_pts + target_concession_mod)
      // If it's still close, make a counter proposal
      if (concession_diff <= counter_concession_max) then
        // -50 triggers automatic counter proposal
        set min_elem_anger := -50
      else
        // -100 rejects the treaty proposal outright
        set min_elem_anger := -100
        // Determine reason to reject
        if (treaty_concession_pts > target_concession_pts) then
          set str_Reject_Reason := "Reject Treaty Too Many Concessions"
          // Debug output
          call Sys_Debug_Print("Politics", "        - Too many concessions")
        else
          set str_Reject_Reason := "Reject Treaty Too Few Concessions"
          // Debug output
          call Sys_Debug_Print("Politics", "        - Too few concessions")
        endif
      endif
    else
      // Debug output
      call Sys_Debug_Print("Politics", "        - Concession check ok")
    endif
  else
    // Debug output
    call Sys_Debug_Print("Politics", "      - Concession check skipped for Peace Treaty")
    set gbl_is_peace_deal := TRUE
  endif

  // For treaty changes, we don't need a specific reject reason
  if (treaty_change) then
    set str_Reject_Reason := ""
  endif

  return min_elem_anger
end

//------------------------------------------------------------------------
// Get_Message_Text
//------------------------------------------------------------------------
function Get_Message_Text returns string
params
  send_msg_type:             long
  received_msg_type:         long
  to_plr:                    long
  to_alliance:               long
  other_plr:                 long
  other_alliance:            long
  proposed_treaty_name:      string
  proposed_alliance_name:    string
  target_system_id:          long
  target_sobj_id:            long
vars
  speech_field:              string := ""
  message_text:              string
  added_text:                string
  current_treaty_name:       string
  system_name:               string
  sobj_name:                 string
  pick:                      long
  field_set:                 boolean := FALSE
  alliance_id:               long
  alliance_name:             string
  is_enemy:                  boolean
  request_time:              string
  request_date:              string
  resource_amt:              string
  resource_type:             string
begin

  // Get our current treaty name
  if (to_plr > 0) then
    set current_treaty_name := Sys_Empire_Politics_Get_Treaty_Name_Between_Players(sys_long_Player_ID, to_plr)
    set is_enemy := Sys_Empire_Politics_Is_Player_Enemy(sys_long_Player_ID, to_plr)
  else
    set current_treaty_name := Sys_Empire_Politics_Get_Treaty_Name_Between_Player_And_Alliance(sys_long_Player_ID, to_alliance)
    set is_enemy := Sys_Empire_Politics_Is_Alliance_Enemy(sys_long_Player_ID, to_alliance)
  endif

  // Three types of messages
  // Send [Message Type] - we are sending something to the to_plr player
  // Response [Friend/Enemy] [Message Type] - we are responding to a message from the to_plr
  // Response [Friend/Enemy] [YES/NO] [Message Type] - we are responding Yes or No to a request from the to_plr

  if (not field_set) then
    if (send_msg_type = POLITICS_MSG_GENERAL_MESSAGE) and (received_msg_type > 0) then
      // Response [Friend/Enemy] [Message Type] - we are responding to a message from the to_plr
      set speech_field := "Response "
      if Sys_Empire_Politics_Is_Player_Enemy(sys_long_Player_ID, to_plr) then
        set speech_field := Sys_Concat_String(speech_field, "Enemy ")
      else
        set speech_field := Sys_Concat_String(speech_field, "Friend ")
      endif
      set speech_field := Sys_Concat_String(speech_field, Sys_Empire_Politics_Get_Message_Type_Name(received_msg_type))
      set field_set := TRUE
    endif
  endif

  if (not field_set) then
    if (send_msg_type = POLITICS_MSG_REQUEST_ACCEPT) or (send_msg_type = POLITICS_MSG_REQUEST_REFUSE) then
      // Response [Friend/Enemy] [YES/NO] [Message Type] - we are responding Yes or No to a request from the to_plr
      // Select the field name based on the message type we received
      set speech_field := "Response "
      if (Sys_Empire_Politics_Is_Player_Enemy(sys_long_Player_ID, to_plr)) then
        set speech_field := Sys_Concat_String(speech_field, "Enemy ")
      else
        set speech_field := Sys_Concat_String(speech_field, "Friend ")
      endif
      if (send_msg_type = POLITICS_MSG_REQUEST_ACCEPT) then
        set speech_field := Sys_Concat_String(speech_field, "YES ")
      endif
      if (send_msg_type = POLITICS_MSG_REQUEST_REFUSE) then
        set speech_field := Sys_Concat_String(speech_field, "NO ")
      endif
      set speech_field := Sys_Concat_String(speech_field, Sys_Empire_Politics_Get_Message_Type_Name(received_msg_type))
      set field_set := TRUE
    endif
  endif

  if (not field_set) then
    // Send [Message Type] - we are sending something to the to_plr player
    // Select the field name based on the message type we are sending
    if (str_Override_Message <> "") then
      set speech_field := Sys_Concat_String("Send ", str_Override_Message)
      set field_set := TRUE
      // Reset override message
      set str_Override_Message := ""
    else
      set speech_field := Sys_Concat_String("Send ", Sys_Empire_Politics_Get_Message_Type_Name(send_msg_type))
      set field_set := TRUE
    endif
  endif

  // Pick a random message number
  set pick := Sys_Get_Random_Long(1, 5)
  set speech_field := Sys_Concat_String(speech_field, " ")
  set speech_field := Sys_Concat_String(speech_field, Sys_Convert_Long_To_String(pick))

  set message_text := Sys_Get_Datafile_Field_Value_As_String(lng_Datafile_Speech_ID, speech_field)

  // Replace flags in our message text

  // Specific flags 
  case send_msg_type
    POLITICS_MSG_REQUEST_ACCEPT:
      // Add our estimated time to comply to the request
      set request_date := Sys_Convert_Long_To_Date_String(sys_long_Game_Date + lng_Politics_Max_Time_To_Honor_A_Request)
      set request_time := Sys_Convert_Long_To_String(lng_Politics_Max_Time_To_Honor_A_Request)
    POLITICS_MSG_REQUEST_REMOVE_SHIPS_FROM_SYSTEM:
      set request_date := Sys_Convert_Long_To_Date_String(sys_long_Game_Date + lng_Politics_Max_Time_To_Honor_A_Request)
      set request_time := Sys_Convert_Long_To_String(Sys_Get_Random_Long(3, 10 - lng_AI_Categorization))
    POLITICS_MSG_REQUEST_REMOVE_COLONIES_FROM_SYSTEM:
      set request_date := Sys_Convert_Long_To_Date_String(sys_long_Game_Date + lng_Politics_Max_Time_To_Honor_A_Request)
      set request_time := Sys_Convert_Long_To_String(Sys_Get_Random_Long(5, 14 - lng_AI_Categorization))
    POLITICS_MSG_REQUEST_ECONOMIC_ASSISTANCE:
      // Determine the resource we need and how much
      if (bool_Race_Minerals_Low) then
        set resource_type := "Minerals"
        set resource_amt := Sys_Convert_Long_To_String(lng_Minerals_Deficit + 2000)
      else
        if (bool_Race_Organics_Low) then
          set resource_type := "Organics"
          set resource_amt := Sys_Convert_Long_To_String(lng_Organics_Deficit + 2000)
        else
          if (bool_Race_Radioactives_Low) then
            set resource_type := "Radioactives"
            set resource_amt := Sys_Convert_Long_To_String(lng_Radioactives_Deficit + 2000)
          endif
        endif
      endif
  endcase

  // Do we have extra text to append to our message?
  if (str_Treaty_Reason <> "") then
    set str_Append_Message := str_Treaty_Reason
  endif
  if (str_Counter_Reason <> "") then
    set str_Append_Message := str_Counter_Reason
  endif
  if (str_Reject_Reason <> "") then
    set str_Append_Message := str_Reject_Reason
  endif
  if (str_Break_Reason <> "") then
    set str_Append_Message := str_Break_Reason
  endif

  // Debug Output
  if (str_Append_Message <> "") then
    call Sys_Debug_Print("Politics", "    - Appended Text Type = " + str_Append_Message)
  endif

  // Add special append text to the message if present
  if (str_Append_Message <> "") then
    // Special case for breaking a treaty with the mega evil player
    if (str_Append_Message = "Break Treaty Mega Evil") then
      set speech_field := "Mega Evil Declaration " + Sys_Convert_Long_To_String(Sys_Get_Random_Long(1, 5))
      set message_text := Sys_Get_Datafile_Field_Value_As_String(lng_Datafile_Speech_ID, speech_field)
    else
      set speech_field := "Append Message " + str_Append_Message
      set added_text := Sys_Get_Datafile_Field_Value_As_String(lng_Datafile_Speech_ID, speech_field)
      set message_text := message_text + " " + added_text
    endif
    // Reset added text variables
    set str_Append_Message := ""
    set str_Treaty_Reason := ""
    set str_Counter_Reason := ""
    set str_Reject_Reason := ""
    set str_Break_Reason := ""
  endif

  // Our names and titles
  set message_text := Sys_Replace_String(message_text, "[%OurEmperorTitle%]", Sys_Empire_Get_Emperor_Title(sys_long_Player_ID), TRUE, TRUE)
  set message_text := Sys_Replace_String(message_text, "[%OurEmperorName%]", Sys_Empire_Get_Emperor_Name(sys_long_Player_ID), TRUE, TRUE)
  set message_text := Sys_Replace_String(message_text, "[%OurEmpireName%]", Sys_Empire_Get_Empire_Name(sys_long_Player_ID), TRUE, TRUE)

  // The receiving player/alliance names and titles
  if (to_plr > 0) then
    set message_text := Sys_Replace_String(message_text, "[%TargetEmperorTitle%]", Sys_Empire_Get_Emperor_Title(to_plr), TRUE, TRUE)
    set message_text := Sys_Replace_String(message_text, "[%TargetEmperorName%]", Sys_Empire_Get_Emperor_Name(to_plr), TRUE, TRUE)
    set message_text := Sys_Replace_String(message_text, "[%TargetEmpireName%]", Sys_Empire_Get_Empire_Name(to_plr), TRUE, TRUE)
  else
    set message_text := Sys_Replace_String(message_text, "[%TargetEmperorTitle%]", Sys_Alliance_Get_Emperor_Title(to_alliance), TRUE, TRUE)
    set message_text := Sys_Replace_String(message_text, "[%TargetEmperorName%]", Sys_Alliance_Get_Emperor_Name(to_alliance), TRUE, TRUE)
    set message_text := Sys_Replace_String(message_text, "[%TargetEmpireName%]", Sys_Alliance_Get_Alliance_Name(to_alliance), TRUE, TRUE)
  endif

  // Other players/alliances involved in the message
  if (other_plr > 0) then
    set message_text := Sys_Replace_String(message_text, "[%OtherEmperorTitle%]", Sys_Empire_Get_Emperor_Title(other_plr), TRUE, TRUE)
    set message_text := Sys_Replace_String(message_text, "[%OtherEmperorName%]", Sys_Empire_Get_Emperor_Name(other_plr), TRUE, TRUE)
    set message_text := Sys_Replace_String(message_text, "[%OtherEmpireName%]", Sys_Empire_Get_Empire_Name(other_plr), TRUE, TRUE)
  endif
  if (other_alliance > 0) then
    set message_text := Sys_Replace_String(message_text, "[%OtherEmperorTitle%]", Sys_Alliance_Get_Emperor_Title(other_alliance), TRUE, TRUE)
    set message_text := Sys_Replace_String(message_text, "[%OtherEmperorName%]", Sys_Alliance_Get_Emperor_Name(other_alliance), TRUE, TRUE)
    set message_text := Sys_Replace_String(message_text, "[%OtherEmpireName%]", Sys_Alliance_Get_Alliance_Name(other_alliance), TRUE, TRUE)
  endif

  // Replace flags for other information in our message
  set message_text := Sys_Replace_String(message_text, "[%RequestDate%]", request_date, TRUE, TRUE)
  set message_text := Sys_Replace_String(message_text, "[%RequestTime%]", request_time, TRUE, TRUE)
  set message_text := Sys_Replace_String(message_text, "[%ResourceType%]", resource_type, TRUE, TRUE)
  set message_text := Sys_Replace_String(message_text, "[%ResourceAmount%]", resource_amt, TRUE, TRUE)

  if (Sys_Length_String(current_treaty_name) > 0) then
    set message_text := Sys_Replace_String(message_text, "[%TreatyName%]", current_treaty_name, TRUE, TRUE)
  endif
  if (Sys_Length_String(proposed_treaty_name) > 0) then
    set message_text := Sys_Replace_String(message_text, "[%ProposedTreatyName%]", proposed_treaty_name, TRUE, TRUE)
  endif
  if (Sys_Length_String(proposed_alliance_name) > 0) then
    set message_text := Sys_Replace_String(message_text, "[%ProposedAllianceName%]", proposed_alliance_name, TRUE, TRUE)
  endif
  if (target_system_id > 0) then
    set system_name := Sys_Get_Solar_System_Name(target_system_id)
    if (Sys_Length_String(system_name) > 0) then
      set message_text := Sys_Replace_String(message_text, "[%SystemName%]", system_name, TRUE, TRUE)
    endif
  endif
  if (target_sobj_id > 0) then
    set sobj_name := Sys_Get_Space_Object_Name(target_sobj_id)
    if (Sys_Length_String(sobj_name) > 0) then
      set message_text := Sys_Replace_String(message_text, "[%SpaceObjectName%]", sobj_name, TRUE, TRUE)
    endif
  endif

  // Alliance Messages
  set alliance_id := 0
  if (send_msg_type = POLITICS_MSG_REQUEST_ACCEPT) or (send_msg_type = POLITICS_MSG_REQUEST_REFUSE) then
    if (received_msg_type = POLITICS_MSG_REQUEST_EMPIRE_BREAK_WITH_ALLIANCE) or (received_msg_type = POLITICS_MSG_REQUEST_TO_JOIN_ALLIANCE) then
      set alliance_id := Sys_Empire_Politics_In_Alliance_ID(sys_long_Player_ID)
    endif
    if (received_msg_type = POLITICS_MSG_REQUEST_EMPIRE_JOIN_WITH_ALLIANCE) then
      if (to_plr > 0) then
        set alliance_id := Sys_Empire_Politics_In_Alliance_ID(to_plr)
      else
        set alliance_id := to_alliance
      endif 
    endif
  endif
  if (send_msg_type = POLITICS_MSG_BREAK_WITH_ALLIANCE) or (send_msg_type = POLITICS_MSG_CHANGE_ALLIANCE_RULE) or (send_msg_type = POLITICS_MSG_REQUEST_EMPIRE_JOIN_WITH_ALLIANCE) then
    set alliance_id := Sys_Empire_Politics_In_Alliance_ID(sys_long_Player_ID)
  endif
  if (send_msg_type = POLITICS_MSG_ADD_EMPIRE_TO_ALLIANCE) or (send_msg_type = POLITICS_MSG_REMOVE_EMPIRE_FROM_ALLIANCE) or (send_msg_type = POLITICS_MSG_PROPOSE_EMPIRE_JOIN_ALLIANCE) then
    set alliance_id := Sys_Empire_Politics_In_Alliance_ID(sys_long_Player_ID)
  endif
  if (send_msg_type = POLITICS_MSG_REQUEST_EMPIRE_BREAK_WITH_ALLIANCE) or (send_msg_type = POLITICS_MSG_REQUEST_TO_JOIN_ALLIANCE) then
    if (to_plr > 0) then
      set alliance_id := Sys_Empire_Politics_In_Alliance_ID(to_plr)
    else
      set alliance_id := to_alliance
    endif
  endif

  return message_text
end

//------------------------------------------------------------------------
// Get_Message_Tone
//------------------------------------------------------------------------
function Get_Message_Tone returns long
params
  to_plr:                    long
  to_alliance:               long
vars
  msg_tone:                  long
  pct_compare:               long
begin

  // Set our default message tone
  set msg_tone := POLITICS_MSG_TONE_TYPE_NEUTRAL

  // Compare our score with the selected player or alliance
  if (to_plr > 0) then
    set pct_compare := lst_Politics_Score_Versus_Player.get(to_plr)
  else
    set pct_compare := lst_Politics_Score_Versus_Alliance.get(to_alliance)
  endif

  if (pct_compare <= lng_Political_Message_Score_Percent_For_Demanding_Tone) then
    set msg_tone := POLITICS_MSG_TONE_TYPE_DEMANDING
  endif
  if (pct_compare >= lng_Political_Message_Score_Percent_For_Pleading_Tone) then
    set msg_tone := POLITICS_MSG_TONE_TYPE_PLEADING
  endif

  return msg_tone
end

//------------------------------------------------------------------------
// Reply_To_Propose_Alliance
//------------------------------------------------------------------------
function Reply_To_Propose_Alliance returns boolean
params
  log_id:                    long
vars
  msg_sent:                  boolean := FALSE
  anger_towards_plr:         long
  fear_towards_plr:          long
  new_log_id:                long
  message_type:              long
  from_plr:                  long
  from_alliance:             long
  new_msg_type:              long
  accept_proposal:           boolean := TRUE
  counter_proposal:          boolean := TRUE
  elements_anger:            long
  alliance_name:             string
  msg_text:                  string
begin

  // Get the message parameters
  set message_type := Sys_Empire_Log_Get_Log_Entry_Message_Type(sys_long_Player_ID, log_id)
  set from_plr := Sys_Empire_Log_Get_Log_Entry_Message_From_Player(sys_long_Player_ID, log_id)
  set from_alliance := Sys_Empire_Log_Get_Log_Entry_Message_From_Alliance(sys_long_Player_ID, log_id)
  set alliance_name := Sys_Empire_Log_Get_Log_Entry_Message_Alliance_Name(sys_long_Player_ID, log_id)

  // Get our anger and fear towards the proposing player or alliance
  if (from_plr > 0) then
    set anger_towards_plr := lst_Politics_Anger_Towards_Player.get(from_plr)
    set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(from_plr)
  else
    set anger_towards_plr := lst_Politics_Anger_Towards_Alliance.get(from_alliance)
    set fear_towards_plr := lst_Politics_Fear_Towards_Alliance.get(from_alliance)
  endif

  // Prepare our response
  set new_log_id := Sys_Empire_Politics_Create_Temporary_Message(sys_long_Player_ID)
  call Sys_Empire_Politics_Copy_Alliance_Rules(sys_long_Player_ID, log_id, new_log_id)
  if (from_plr > 0) then
    call Sys_Empire_Politics_Set_Message_To_Empire(new_log_id, from_plr)
  else
    call Sys_Empire_Politics_Set_Message_To_Alliance(new_log_id, from_alliance)
  endif
  call Sys_Empire_Politics_Set_Message_Tone(new_log_id, Get_Message_Tone(from_plr, from_alliance))

  // Get the highest anger element in the alliance proposal
  set elements_anger := Compute_Max_Anger_For_Alliance_Elements(log_id)

  // Do we accept the alliance proposal?
  if (accept_proposal) then
    set accept_proposal := (anger_towards_plr <= lng_Politics_Max_Anger_To_Accept_Alliance - fear_towards_plr)
  endif
  if (accept_proposal) then
    set accept_proposal := (anger_towards_plr <= elements_anger)
  endif

  // Do not accept an alliance offer from the mega evil player!
  if (from_plr > 0) and Sys_Is_Game_Using_Ultimate_Evil_Player() and Sys_Empire_Politics_Is_Player_The_Ultimate_Evil(sys_long_Player_ID, from_plr) then
    set accept_proposal := FALSE
  endif

  // Do not accept an alliance offer from human players when we are using AI team mode!
  if Sys_Is_Game_Using_Teams() then
    set accept_proposal := Sys_Empire_Politics_Is_Player_On_Our_Team(sys_long_Player_ID, from_plr)
  endif

  // Do we accept the alliance proposal?
  if (accept_proposal) then
    set new_msg_type := POLITICS_MSG_ACCEPT_ALLIANCE
  else
    // Make a counter proposal if our anger is below the threshold to counter
    if (counter_proposal) then
      set counter_proposal := (anger_towards_plr <= lng_Politics_Max_Anger_To_Counter_Alliance - fear_towards_plr)
    endif
    // Set a random chance we will make a counter proposal
    if (counter_proposal) and (Sys_Get_Random_Long(1, 3) > 1) then
      set counter_proposal := FALSE
    endif
    // Do not make a counter proposal to the mega evil player!
    if (from_plr > 0) and Sys_Is_Game_Using_Ultimate_Evil_Player() and Sys_Empire_Politics_Is_Player_The_Ultimate_Evil(sys_long_Player_ID, from_plr) then
        set counter_proposal := FALSE
    endif
    // Propose changes
    if (counter_proposal) then
      set counter_proposal := Compute_Counter_Alliance_Elements(new_log_id, anger_towards_plr, fear_towards_plr)
    endif
  
    // Do we counter the alliance proposal?
    if (counter_proposal) then
      set new_msg_type := POLITICS_MSG_COUNTER_ALLIANCE_PROPOSAL
    else
      // Refuse the alliance proposal
      set new_msg_type := POLITICS_MSG_REFUSE_ALLIANCE
    endif
  endif

  // Send our response
  if (new_msg_type > 0) then
    set msg_text := Get_Message_Text(new_msg_type, message_type, from_plr, from_alliance, 0, 0, "", alliance_name, 0, 0)
    if (Sys_Length_String(msg_text) > 0) then
      call Sys_Empire_Politics_Set_Message_Type(new_log_id, new_msg_type)
      call Sys_Empire_Politics_Set_Message_Text(new_log_id, msg_text)
      set msg_sent := Sys_Empire_Politics_Send_Message(new_log_id)
      // Debug output
      call Sys_Debug_Print("Politics", "    - Message Text = " + msg_text)
    endif
  endif
  
  return msg_sent
end

//------------------------------------------------------------------------
// Compute_Counter_Alliance_Elements
//------------------------------------------------------------------------
function Compute_Counter_Alliance_Elements returns boolean
params
  new_log_id:                long
  anger_towards_plr:         long
  fear_towards_plr:          long
vars
  total_max_anger:           long
  this_max_anger:            long
  list_count:                long
  list_index:                long
  lst_elem_type:             longlist
  lst_elem_value:            longlist
  elem_type:                 long
  elem_value:                long
  check_count:               long
  anger_towards_plr:         long
  fear_towards_plr:          long
  new_value:                 long
  lowest_anger:              long
  this_value:                long
  proposal_ok:               boolean := FALSE
  start_pos:                 long
begin

  // Get the Proposed Alliance elements
  call Sys_Empire_Log_Get_Log_Entry_Message_Alliance_Elements(sys_long_Player_ID, new_log_id, lst_elem_type, lst_elem_value)

  // Go through the alliance elements
  set list_count := lst_elem_type.count()
  if (list_count > 0) then
    for list_index := 1 to list_count do
      set elem_type := lst_elem_type.get(list_index)
      set elem_value := lst_elem_value.get(list_index)

      set check_count := lng_Politics_Alliance_Elements_Allowed_Type.count()
      set start_pos := lng_Politics_Alliance_Elements_Allowed_Type.IndexOf(elem_type)
      if (start_pos > 0) then
        set lowest_anger := 100
        set new_value := 0
        loop
          set this_value := lng_Politics_Alliance_Elements_Allowed_Value.get(start_pos)
          set this_max_anger := lng_Politics_Alliance_Elements_Allowed_Max_Anger.get(start_pos) - fear_towards_plr
          if (this_value <> elem_value) then
            if (anger_towards_plr <= this_max_anger) and (this_max_anger <= lowest_anger) then
              set new_value := this_value
              set lowest_anger := this_max_anger
            endif
          endif
          exitwhen (lng_Politics_Alliance_Elements_Allowed_Type.get(start_pos) <> elem_type) or (start_pos >= check_count)
          set start_pos := start_pos + 1
        endloop
        call lst_elem_value.Set(list_index, new_value)
      endif
    endfor

    set list_index := 0
    loop
      set list_index := list_index + 1
      if (lst_elem_value.Get(list_index) = 0) then
        call lst_elem_type.delete(list_index)
        call lst_elem_value.delete(list_index)
        set list_index := list_index - 1
        set list_count := list_count - 1
      endif
      exitwhen (list_index >= list_count) or (list_count = 0)
    endloop
    set proposal_ok := (list_count > 0)
  endif

  if (proposal_ok) then
    call Sys_Empire_Log_Set_Log_Entry_Message_Alliance_Elements(new_log_id, lst_elem_type, lst_elem_value)
  endif

  return proposal_ok
end

//------------------------------------------------------------------------
// Compute_Max_Anger_For_Alliance_Elements
//------------------------------------------------------------------------
function Compute_Max_Anger_For_Alliance_Elements returns long
params
  log_id:                    long
vars
  total_max_anger:           long := 100
  this_max_anger:            long
  list_count:                long
  list_index:                long
  lst_elem_type:             longlist
  lst_elem_value:            longlist
  elem_type:                 long
  elem_value:                long
  check_count:               long
  start_pos:                 long
begin

  // Get the proposed alliance elements
  call Sys_Empire_Log_Get_Log_Entry_Message_Alliance_Elements(sys_long_Player_ID, log_id, lst_elem_type, lst_elem_value)

  // Description pending
  set list_count := lst_elem_type.count()
  if (list_count > 0) then
    for list_index := 1 to list_count do
      set elem_type := lst_elem_type.get(list_index)
      set elem_value := lst_elem_value.get(list_index)
      set check_count := lng_Politics_Alliance_Elements_Allowed_Type.count()
      set start_pos := lng_Politics_Alliance_Elements_Allowed_Type.IndexOf(elem_type)
      if (start_pos > 0) then
        set this_max_anger := -10
        loop
          if (lng_Politics_Alliance_Elements_Allowed_Value.get(start_pos) = elem_value) then
            set this_max_anger := lng_Politics_Alliance_Elements_Allowed_Max_Anger.get(start_pos)
          endif
          exitwhen (this_max_anger > -10) or (lng_Politics_Alliance_Elements_Allowed_Type.get(start_pos) <> elem_type) or (start_pos >= check_count)
          set start_pos := start_pos + 1
        endloop
        if (this_max_anger > -10) then
          if (this_max_anger < total_max_anger) then
            set total_max_anger := this_max_anger
          endif
        endif
      endif
    endfor
  endif

  return total_max_anger
end

//------------------------------------------------------------------------
// Reply_To_Request_Join_Alliance
//------------------------------------------------------------------------
function Reply_To_Request_Join_Alliance returns boolean
params
  log_id:                    long
vars
  msg_sent:                  boolean := FALSE
begin

  // Request to join the Alliance if we are not in one and are friendly towards it

  return msg_sent
end

//------------------------------------------------------------------------
// Reply_To_General_Message
//------------------------------------------------------------------------
function Reply_To_General_Message returns boolean
params
  log_id:                    long
vars
  msg_sent:                  boolean := FALSE
  message_type:              long
  new_log_id:                long
  from_plr:                  long
  from_alliance:             long
  other_plr:                 long
  other_alliance:            long
  target_system_id:          long
  target_sobj_id:            long
  num_times_treaty_broken:   long
  msg_text:                  string
begin

  // Get the message parameters
  set message_type := Sys_Empire_Log_Get_Log_Entry_Message_Type(sys_long_Player_ID, log_id)
  set from_plr := Sys_Empire_Log_Get_Log_Entry_Message_From_Player(sys_long_Player_ID, log_id)
  set from_alliance := Sys_Empire_Log_Get_Log_Entry_Message_From_Alliance(sys_long_Player_ID, log_id)
  set other_plr := Sys_Empire_Log_Get_Log_Entry_Message_Param_Against_Player(sys_long_Player_ID, log_id)
  set other_alliance := Sys_Empire_Log_Get_Log_Entry_Message_Param_Against_Alliance(sys_long_Player_ID, log_id)
  set target_system_id := Sys_Empire_Log_Get_Log_Entry_Message_Param_Target_System(sys_long_Player_ID, log_id)
  set target_sobj_id := Sys_Empire_Log_Get_Log_Entry_Message_Param_Target_Space_Object_ID(sys_long_Player_ID, log_id)

  // Is this a break treaty message?
  if (message_type = POLITICS_MSG_BREAK_TREATY) then
    call lst_Date_Last_Treaty_Broken.set(from_plr, sys_long_Game_Date)
    // Count the number of times this has happened!
    set num_times_treaty_broken := lst_Num_Times_Treaty_Broken.get(from_plr) + 1
    call lst_Num_Times_Treaty_Broken.set(from_plr, num_times_treaty_broken)
    // Debug output
    call Sys_Debug_Print("Politics", "  - " + Sys_Empire_Get_Empire_Name(from_plr) + " broke our treaty; Number of times this has happened = " + Sys_Convert_Long_To_String(num_times_treaty_broken))
  endif

  // Create message
  set new_log_id := Sys_Empire_Politics_Create_Temporary_Message(sys_long_Player_ID)
  set msg_text := Get_Message_Text(POLITICS_MSG_GENERAL_MESSAGE, message_type, from_plr, from_alliance, other_plr, other_alliance, "", "", target_system_id, target_sobj_id)

  if (Sys_Length_String(msg_text) > 0) then
    if (from_plr > 0) then
      call Sys_Empire_Politics_Set_Message_To_Empire(new_log_id, from_plr)
      // Debug output
      call Sys_Debug_Print("Politics", "    - Sent a reply of " + Get_Message_Type(POLITICS_MSG_GENERAL_MESSAGE) + " to the " Sys_Empire_Get_Empire_Name(from_plr))
    else
      call Sys_Empire_Politics_Set_Message_To_Alliance(new_log_id, from_alliance)
    endif
    call Sys_Empire_Politics_Set_Message_Tone(new_log_id, Get_Message_Tone(from_plr, from_alliance))
    call Sys_Empire_Politics_Set_Message_Type(new_log_id, POLITICS_MSG_GENERAL_MESSAGE)
    call Sys_Empire_Politics_Set_Message_Text(new_log_id, msg_text)
    set msg_sent := Sys_Empire_Politics_Send_Message(new_log_id)
    // Debug output
    call Sys_Debug_Print("Politics", "      - Message Text = " + msg_text)
  endif

  return msg_sent
end

//------------------------------------------------------------------------
// Reply_To_Give_Gift
//------------------------------------------------------------------------
function Reply_To_Give_Gift returns boolean
params
  log_id:                    long
vars
  msg_sent:                  boolean := FALSE
  anger_towards_plr:         long
  fear_towards_plr:          long
  new_log_id:                long
  message_type:              long
  from_plr:                  long
  from_alliance:             long
  new_msg_type:              long
  accept_gift:               boolean := TRUE
  msg_text:                  string
begin

  // Get the message parameters
  set message_type := Sys_Empire_Log_Get_Log_Entry_Message_Type(sys_long_Player_ID, log_id)
  set from_plr := Sys_Empire_Log_Get_Log_Entry_Message_From_Player(sys_long_Player_ID, log_id)
  set from_alliance := Sys_Empire_Log_Get_Log_Entry_Message_From_Alliance(sys_long_Player_ID, log_id)

  // Prepare our reply
  set new_log_id := Sys_Empire_Politics_Create_Temporary_Message(sys_long_Player_ID)

  if (from_plr > 0) then
    call Sys_Empire_Politics_Set_Message_To_Empire(new_log_id, from_plr)
    // Debug output
    call Sys_Debug_Print("Politics", "  - Gift sent from the " + Sys_Empire_Get_Empire_Name(from_plr))
  else
    call Sys_Empire_Politics_Set_Message_To_Alliance(new_log_id, from_alliance)
    // Debug output
    call Sys_Debug_Print("Politics", "  - Gift sent from the " + Sys_Alliance_Get_Alliance_Name(from_alliance))
  endif

  // Debug output (from players only)
  if (from_plr > 0) then
    call List_Package_Items(log_id, PACKAGE_TYPE_GIVE)
  endif

  call Sys_Empire_Politics_Set_Message_Tone(new_log_id, Get_Message_Tone(from_plr, from_alliance))
  call Sys_Empire_Politics_Copy_Packages(sys_long_Player_ID, log_id, new_log_id)

  // Note our anger and fear towards the gifting player or alliance
  if (from_plr > 0) then
    set anger_towards_plr := lst_Politics_Anger_Towards_Player.get(from_plr)
    set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(from_plr)
  else
    set anger_towards_plr := lst_Politics_Anger_Towards_Alliance.get(from_alliance)
    set fear_towards_plr := lst_Politics_Fear_Towards_Alliance.get(from_alliance)
  endif

  // Do we accept the gift?
  set accept_gift := (anger_towards_plr <= lng_Politics_Max_Anger_To_Accept_Gift)

  if (from_plr > 0) then
    // Don't accept gifts from the mega evil player
    if (accept_gift) and Sys_Is_Game_Using_Ultimate_Evil_Player() then
      set accept_gift := (not Sys_Empire_Politics_Is_Player_The_Ultimate_Evil(sys_long_Player_ID, from_plr))
    endif
    // Don't accept gifts from human players not on our team!
    if (accept_gift) and Sys_Is_Game_Using_Teams() then
      set accept_gift := Sys_Empire_Politics_Is_Player_On_Our_Team(sys_long_Player_ID, from_plr)
    endif
  endif

  // Set our reply to accept the gift
  if (accept_gift) then
    set new_msg_type := POLITICS_MSG_ACCEPT_GIFT
    // Get the gift
    call Sys_Empire_Politics_Switch_Give_And_Get_Packages(new_log_id)
    // Debug output
    call Sys_Debug_Print("Politics", "    - Gift Accepted")
  else
    // Set our reply to refuse the gift
    set new_msg_type := POLITICS_MSG_REFUSE_GIFT
    // Debug output
    call Sys_Debug_Print("Politics", "    - Gift Rejected")
  endif

  // Send our reply
  if (new_msg_type > 0) then
    set msg_text := Get_Message_Text(new_msg_type, message_type, from_plr, from_alliance, 0, 0, "", "", 0, 0)
    if (Sys_Length_String(msg_text) > 0) then
      call Sys_Empire_Politics_Set_Message_Type(new_log_id, new_msg_type)
      call Sys_Empire_Politics_Set_Message_Text(new_log_id, msg_text)
      set msg_sent := Sys_Empire_Politics_Send_Message(new_log_id)
      // Debug output
      call Sys_Debug_Print("Politics", "    - Sent a reply of " + Get_Message_Type(new_msg_type) + " to the " Sys_Empire_Get_Empire_Name(from_plr))
      call Sys_Debug_Print("Politics", "      - Message Text = " + msg_text)
    endif
  endif
  
  return msg_sent
end

//------------------------------------------------------------------------
// Reply_To_Propose_Trade
//------------------------------------------------------------------------
function Reply_To_Propose_Trade returns boolean
params
  log_id:                    long
vars
  msg_sent:                  boolean := FALSE
  anger_towards_plr:         long
  fear_towards_plr:          long
  new_log_id:                long
  message_type:              long
  from_plr:                  long
  from_alliance:             long
  new_msg_type:              long
  accept_trade:              boolean := TRUE
  counter_trade:             boolean := FALSE
  give_value:                long
  get_value:                 long
  trade_mod:                 long
  trade_buffer:              long
  msg_text:                  string
  extra_msg_text:            string
begin

  // Get the message parameters
  set message_type := Sys_Empire_Log_Get_Log_Entry_Message_Type(sys_long_Player_ID, log_id)
  set from_plr := Sys_Empire_Log_Get_Log_Entry_Message_From_Player(sys_long_Player_ID, log_id)
  set from_alliance := Sys_Empire_Log_Get_Log_Entry_Message_From_Alliance(sys_long_Player_ID, log_id)

  // Prepare our reply
  set new_log_id := Sys_Empire_Politics_Create_Temporary_Message(sys_long_Player_ID)
  call Sys_Empire_Politics_Set_Message_To_Empire(new_log_id, from_plr)
  call Sys_Empire_Politics_Set_Message_Tone(new_log_id, Get_Message_Tone(from_plr, from_alliance))
  call Sys_Empire_Politics_Copy_Packages(sys_long_Player_ID, log_id, new_log_id)

  // Note our anger and fear towards the proposing player or alliance
  if (from_plr > 0) then
    set anger_towards_plr := lst_Politics_Anger_Towards_Player.get(from_plr)
    set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(from_plr)
    // Debug output
    call Sys_Debug_Print("Politics", "  - Trade Request from the " + Sys_Empire_Get_Empire_Name(from_plr))
  else
    set anger_towards_plr := lst_Politics_Anger_Towards_Alliance.get(from_alliance)
    set fear_towards_plr := lst_Politics_Fear_Towards_Alliance.get(from_alliance)
    // Debug output
    call Sys_Debug_Print("Politics", "  - Trade Request from the " + Sys_Alliance_Get_Alliance_Name(from_plr))
  endif

  // Debug output
  call Sys_Debug_Print("Politics", "  - Give ")
  call List_Package_Items(log_id, PACKAGE_TYPE_GET)
  call Sys_Debug_Print("Politics", "  - Get ")
  call List_Package_Items(log_id, PACKAGE_TYPE_GIVE)

  // Set our trade modifiers
  set trade_mod := Sys_Divide_Long(fear_towards_plr, 2)
  set trade_buffer := Sys_Get_Random_Long(-5, 5)

  // Calculate the value of the trade package
  // Get items = Items the proposing empire gets (we give)
  // Give items = Items the proposing empire gives (we get)
  set get_value := Calculate_Package_Value(log_id, PACKAGE_TYPE_GET, from_plr)
  set give_value := Calculate_Package_Value(log_id, PACKAGE_TYPE_GIVE, from_plr)

  // Do we have the items required in the trade?
  if (not Sys_Empire_Log_Do_We_Have_Package_Items(sys_long_Player_ID, log_id, PACKAGE_TYPE_GET)) then
    set accept_trade := FALSE
    set extra_msg_text := " We do not have all the items requested."
  endif

  // Does our anger level allow us to accept the trade?
  if (accept_trade) and (anger_towards_plr <= lng_Politics_Max_Anger_To_Trade + fear_towards_plr) then
    // Still accept lopsided trades!
    if (get_value > Sys_Divide_Long(give_value, 2)) then
      set accept_trade := FALSE
    endif
  endif

  // Are there "Any" items we need to counter instead?
  if (accept_trade) then
    // We have to counter if the trade package has "Any" items
    if Sys_Empire_Log_Does_Package_Have_Any_Unspecified_Items(sys_long_Player_ID, log_id, PACKAGE_TYPE_GET) then
      set accept_trade := FALSE
      set counter_trade := TRUE
    endif
  endif

  // Do we accept the trade based on its contents?
  if (accept_trade) then
    if Sys_Empire_Politics_Is_Player_Enemy(sys_long_Player_ID, from_plr) or Sys_Empire_Politics_Is_Alliance_Enemy(sys_long_Player_ID, from_alliance) then
      set accept_trade := (give_value >= Sys_Trunc(get_value * (lng_Politics_Trade_Value_Percent_For_Enemy - trade_mod + trade_buffer) / 100))
    else
      set accept_trade := (give_value >= Sys_Trunc(get_value * (lng_Politics_Trade_Value_Percent_For_Friend - trade_mod + trade_buffer) / 100))
    endif
  endif

  // Set our reply if we successfully accepted the trade
  if (accept_trade) then
    set new_msg_type := POLITICS_MSG_ACCEPT_TRADE
    // Perform the trade
    call Sys_Empire_Politics_Switch_Give_And_Get_Packages(new_log_id)
    // Debug output
    call Sys_Debug_Print("Politics", "  - Trade Accepted")
  endif

  // Are we countering the trade?
  if (counter_trade) then
    // Debug output
    call Sys_Debug_Print("Politics", "  - Countered Trade")
    // Change "Any" items to what we want
    if Change_Package_Any_Items_To_What_We_Want(new_log_id, PACKAGE_TYPE_GET) then
      // Recalculate the value of the item we are giving
      set get_value := Calculate_Package_Value(new_log_id, PACKAGE_TYPE_GET, from_plr)

      // Do we accept the trade based on its updated contents?
      if Sys_Empire_Politics_Is_Player_Enemy(sys_long_Player_ID, from_plr) then
        set counter_trade := (give_value >= Sys_Divide_Long(get_value * (lng_Politics_Trade_Value_Percent_For_Enemy - trade_mod + trade_buffer), 100))
      else
        set counter_trade := (give_value >= Sys_Divide_Long(get_value * (lng_Politics_Trade_Value_Percent_For_Friend - trade_mod + trade_buffer), 100))
      endif
  else
    // If we don't have an "Any" item, we can't counter the trade proposal
    set counter_trade := FALSE
    set extra_msg_text := " We did not have any unique items to trade in the area requested."
  endif

    // Set our reply if we successfully countered the trade
    if (counter_trade) then
      // Set our reply to counter the trade
      call Sys_Empire_Politics_Switch_Give_And_Get_Packages(new_log_id)
      set new_msg_type := POLITICS_MSG_COUNTER_TRADE
    endif
  endif

  // Set our reply to refuse the trade if we did not accept or countered the trade
  if (not accept_trade) and (not counter_trade) then
    set new_msg_type := POLITICS_MSG_REFUSE_TRADE
  endif

  // Send our reply
  if (new_msg_type > 0) then
    // Get the message text
    set msg_text := Get_Message_Text(new_msg_type, message_type, from_plr, from_alliance, 0, 0, "", "", 0, 0)
    // Add the tone and text to our message
    if (Sys_Length_String(msg_text) > 0) then
      call Sys_Empire_Politics_Set_Message_Type(new_log_id, new_msg_type)
      call Sys_Empire_Politics_Set_Message_Text(new_log_id, msg_text)
      set msg_sent := Sys_Empire_Politics_Send_Message(new_log_id)
      // Debug output
      call Sys_Debug_Print("Politics", "  - Sent a reply of " + Get_Message_Type(new_msg_type) + " to the " Sys_Empire_Get_Empire_Name(from_plr))
      call Sys_Debug_Print("Politics", "    - Message Text = " + msg_text)
    endif
  endif
  
  return msg_sent
end

//------------------------------------------------------------------------
// Calculate_Package_Value
//------------------------------------------------------------------------
function Calculate_Package_Value returns long
params
  log_id:                    long
  package_type:              long
  from_plr:                  long
vars
  this_value:                long
  total_value:               long
  list_count:                long
  list_index:                long
  lst_item_type:             longlist
  lst_item_id:               longlist
  lst_item_amount:           longlist
  item_type:                 long
  item_id:                   long
  item_amount:               long
  item_sys_loc:              long
  item_sect_loc:             long
  item_dist:                 long
  num_comps:                 long
  dmg_comps:                 long
  dmg_pct:                   long
  minerals_mod:              real := 1.0
  organics_mod:              real := 0.5
  radioactives_mod:          real := 0.5
  res_value:                 resources
  tech_value:                real
  check_plr:                 long
  other_plr:                 long
  debug_str:                 string
begin

  // Get the items in the gift or trade package
  call Sys_Empire_Log_Get_Package_Items(sys_long_Player_ID, log_id, package_type, lst_item_type, lst_item_id, lst_item_amount)

  // Adjust our resource modifiers
  if (bool_Race_Uses_Crystalline_Tech) or (bool_Race_Uses_Temporal_Tech) then
    set radioactives_mod := radioactives_mod + 0.5
  endif
  if (bool_Race_Uses_Organic_Tech) then
    set organics_mod := organics_mod + 0.5
  endif

  if (bool_Race_Minerals_Low) then
    set minerals_mod := minerals_mod + 1.0
  endif
  if (bool_Race_Organics_Low) then
    set organics_mod := organics_mod + 1.0
  endif
  if (bool_Race_Radioactives_Low) then
    set radioactives_mod := radioactives_mod + 1.0
  endif

  // Debug output
  if (package_type = PACKAGE_TYPE_GET) then
    call Sys_Debug_Print("Politics", "    - Items we give:")
  else
    call Sys_Debug_Print("Politics", "    - Items we get:")
  endif

  // For some items, their value is based on our evaluation and other times on our estimate of what its worth to the proposing empire
  if (package_type = PACKAGE_TYPE_GIVE) and (from_plr > 0) then
    set check_plr := sys_long_Player_ID
    set other_plr := from_plr
  else
    set check_plr := from_plr
    set other_plr := sys_long_Player_ID
  endif

  // Calculate the value of the gift or trade package
  set list_count := lst_item_type.count()

  if (list_count > 0) then
    for list_index := 1 to list_count do
      set item_type := lst_item_type.get(list_index)
      set item_id := lst_item_id.get(list_index)
      set item_amount := lst_item_amount.get(list_index)
      set this_value := 0
      // Determine the value of the item
      case item_type
        MESSAGE_PACKAGE_ITEM_TYPE_SYSTEM:
          // If this is a home system, increase the value more
          if (Sys_Get_Empire_Home_System(check_plr) = item_id) then
            set this_value := 500000
          endif
          // Count the number of colonizable planets in the system
          set this_value := this_value + 100000 * Sys_Get_Solar_System_Colonizable_Planets_Count(sys_long_Player_ID, item_id)
          // Note the resource value of the system
          set this_value := this_value + (1000 * Sys_Trunc(lst_AI_System_Value.get(item_id)))
          // Count the number of ships in the system
          set this_value := this_value + 5000 * Sys_Get_Number_Of_Player_Ships_In_System(check_plr, item_id)
          // Debug output
          set debug_str := Sys_Get_Solar_System_Name(item_id)
          call Sys_Debug_Print("Politics", "      - " + debug_str + " System worth " + Sys_Convert_Long_To_String(this_value) + " points")
        MESSAGE_PACKAGE_ITEM_TYPE_PLANET:
          // Get the planet's basic details
          set res_value := Sys_Get_Space_Object_Planet_Value(item_id)
          set item_sys_loc := Sys_Get_Space_Object_System_Location(item_id)
          set item_sect_loc := Sys_Get_Space_Object_Sector_Location(item_id)
          set item_dist := Get_Distance_To_Nearest_Colony(item_sys_loc, item_sect_loc)
          // Determine the trade/gift value of the planet
          if Sys_Can_Colonize_Planet(sys_long_Player_ID, item_id) then
            // Facility value
            if Is_Planet_Breathable_By_Population(item_id) or Sys_Is_Planet_Breathable(item_id, sys_long_Player_ID) then
              set this_value := this_value + (Sys_Get_Space_Object_Facility_Total_Space(item_id) * 5)
            else
              set this_value := this_value + (Sys_Get_Space_Object_Facility_Total_Space(item_id) * 1)
            endif
            // Resource value
            if Sys_Is_Finite_Resource_Game() then
              set this_value := this_value + Sys_Trunc((res_value.get(1) * minerals_mod / 500) + (res_value.get(2) * organics_mod / 500) + (res_value.get(3) * radioactives_mod / 500))
            else
              set this_value := this_value + Sys_Trunc((res_value.get(1) * minerals_mod * 10) + (res_value.get(2) * organics_mod * 10) + (res_value.get(3) * radioactives_mod * 10))
            endif
          endif
          // Value adjustment for distance to our colonies
          set this_value := this_value + 5000 - (item_dist * 50)
          // Value adjustment for no spaceport in system
          if (lst_AI_Our_Spaceport_Systems.get(item_sys_loc) = 0) then
            set this_value := this_value - 5000
          endif
          // Debug output
          set debug_str := Sys_Get_Space_Object_Name(item_id)
          call Sys_Debug_Print("Politics", "      - Planet " + debug_str + " worth " + Sys_Convert_Long_To_String(this_value) + " points")
        MESSAGE_PACKAGE_ITEM_TYPE_RESOURCE:
          // Resource values are 1 point per kT
          set this_value := Sys_Trunc(item_amount * ((minerals_mod + organics_mod + radioactives_mod) / 3))
          // Debug output
          call Sys_Debug_Print("Politics", "      - Resources worth " + Sys_Convert_Long_To_String(this_value) + " points")
        MESSAGE_PACKAGE_ITEM_TYPE_TECHNOLOGY:
          // Bug Workaround: Set tech level of technology from proposing player
          set item_amount := Sys_Get_Empire_Research_Tech_Level(other_plr, item_id)
          // Is this a visible tech area?
          if Sys_Is_Empire_Research_Tech_Visible(check_plr, item_id) then
            set tech_value := Sys_Get_Empire_Research_Tech_Area_Cost_For_Next_Level(check_plr, item_id)
            // Calculate the value of the tech area
            if (item_amount > Sys_Get_Empire_Research_Tech_Level(check_plr, item_id)) then
              set this_value := this_value + Sys_Trunc(tech_value * Sys_Min_Long(1, (item_amount - Sys_Get_Empire_Research_Tech_Level(check_plr, item_id))))
            endif
          else
            // This tech area is not available
            set this_value := -5000
          endif
          // Debug output
          set debug_str := Sys_Get_Tech_Area_Name(item_id)
          call Sys_Debug_Print("Politics", "      - " + debug_str + " tech area worth " + Sys_Convert_Long_To_String(this_value) + " points")
        MESSAGE_PACKAGE_ITEM_TYPE_SHIP:
          // Get the ship's details
          set item_sys_loc := Sys_Get_Space_Object_System_Location(item_id)
          set item_sect_loc := Sys_Get_Space_Object_Sector_Location(item_id)
          set item_dist := Get_Distance_To_Nearest_Colony(item_sys_loc, item_sect_loc)
          set num_comps := Sys_Get_Space_Object_Comp_Count(item_id)
          set dmg_comps := Sys_Get_Space_Object_Number_Of_Damaged_Components(item_id)
          set dmg_pct := Sys_Trunc((dmg_comps / num_comps) * 100)
          // Estimate the ship's value by its scrap value
          set res_value := Sys_Get_Space_Object_Scrap_Value(item_id)
          set this_value := this_value + Sys_Trunc((res_value.get(1) * 5) + (res_value.get(2) * 2) + (res_value.get(3) * 5))
          // Adjust the value based on the distance to our colonies
          set this_value := this_value + 1000 - (item_dist * 10)
          // Reduce the value if the ship has lost its critical components
          if Sys_Has_Space_Object_Lost_Critical_Components(item_id) then
            set this_value := this_value - 5000
          endif
          // Reduce the value if the ship's movement is 0
           if (not Sys_Is_Space_Object_Base(item_id)) then
             if (Sys_Get_Space_Object_Maximum_Movement(item_id) = 0) then
               set this_value := this_value - 5000
             endif
           endif
          // Reduce the value for the ship's damage
          set this_value := this_value - (dmg_pct * 25)
          // Debug output
          set debug_str := Sys_Get_Space_Object_Name(item_id)
          call Sys_Debug_Print("Politics", "      - Vehicle " + debug_str + " worth " + Sys_Convert_Long_To_String(this_value) + " points")
        MESSAGE_PACKAGE_ITEM_TYPE_STARCHART:
          // Value depends on if objects will be visible or not
          if (not Sys_Have_Seen_System(sys_long_Player_ID, item_id)) then
            set this_value := 5000
          else
            set this_value := 0
          endif
          // Debug output
          set debug_str := Sys_Get_Solar_System_Name(item_id)
          call Sys_Debug_Print("Politics", "      - " + debug_str + " System starchart worth " + Sys_Convert_Long_To_String(this_value) + " points")
        MESSAGE_PACKAGE_ITEM_TYPE_COMM:
          // Value needs to be determined
          set this_value := 5000
          // Debug output
          call Sys_Debug_Print("Politics", "      - Comm Channel worth " + Sys_Convert_Long_To_String(this_value) + " points")
      endcase
      // Add the total
      set total_value := total_value + this_value
    endfor
    // Debug output
    call Sys_Debug_Print("Politics", "      - Package value is worth " + Sys_Convert_Long_To_String(total_value) + " points")
  endif

  return total_value
end

//------------------------------------------------------------------------
// Change_Package_Any_Items_To_What_We_Want
//------------------------------------------------------------------------
function Change_Package_Any_Items_To_What_We_Want returns boolean
params
  log_id:                    long
  package_type:              long
vars
  lst_item_type:             longlist
  lst_item_id:               longlist
  lst_item_amount:           longlist
  list_count:                long
  list_index:                long
  item_type:                 long
  sel_item_type:             long
  from_plr:                  long
  from_alliance:             long
  lst_sel_items:             longlist
  pick:                      long
  any_items_replaced:        boolean := TRUE
begin

  // Get the message parameters
  call Sys_Empire_Log_Get_Package_Items(sys_long_Player_ID, log_id, package_type, lst_item_type, lst_item_id, lst_item_amount)
  set from_plr := Sys_Empire_Log_Get_Log_Entry_Message_From_Player(sys_long_Player_ID, log_id)
  set from_alliance := Sys_Empire_Log_Get_Log_Entry_Message_From_Alliance(sys_long_Player_ID, log_id)

  // Process the package items and for "any" items, find an actual item to put into the package
  set list_count := lst_item_type.count()
  if (list_count > 0) then
    // Check for the specific "any" item type
    for list_index := 1 to list_count do
      set item_type := lst_item_type.get(list_index)
      set sel_item_type := 0
      case item_type
        MESSAGE_PACKAGE_ITEM_TYPE_ANY_PLANET:
          set sel_item_type := MESSAGE_PACKAGE_ITEM_TYPE_PLANET
        MESSAGE_PACKAGE_ITEM_TYPE_ANY_TECHNOLOGY:
          set sel_item_type := MESSAGE_PACKAGE_ITEM_TYPE_TECHNOLOGY
        MESSAGE_PACKAGE_ITEM_TYPE_ANY_SHIP:
          set sel_item_type := MESSAGE_PACKAGE_ITEM_TYPE_SHIP
        MESSAGE_PACKAGE_ITEM_TYPE_ANY_STARCHART:
          set sel_item_type := MESSAGE_PACKAGE_ITEM_TYPE_STARCHART
        MESSAGE_PACKAGE_ITEM_TYPE_ANY_COMM:
          set sel_item_type := MESSAGE_PACKAGE_ITEM_TYPE_COMM
      endcase
      // Create a list of possible items that can be the "any" item
      if (sel_item_type > 0) then
        if (from_plr > 0) then
          call Sys_Empire_Log_Get_Package_Selection_List(ENTITY_TYPE_EMPIRE, sys_long_Player_ID, ENTITY_TYPE_EMPIRE, from_plr, lst_sel_items, sel_item_type, TRUE, FALSE)
        else
          call Sys_Empire_Log_Get_Package_Selection_List(ENTITY_TYPE_EMPIRE, sys_long_Player_ID, ENTITY_TYPE_ALLIANCE, from_alliance, lst_sel_items, sel_item_type, TRUE, FALSE)
        endif
        // Pick a random item from the compiled list of possible "any" items
        if (lst_sel_items.count() > 0) then
          set pick := Sys_Get_Random_Long(1, lst_sel_items.count())
          call Sys_Empire_Log_Add_Package_Items(log_id, package_type, sel_item_type, lst_sel_items.get(pick), 1)
        else
          set any_items_replaced := FALSE
        endif
      endif
    endfor
  endif

  return any_items_replaced
end

//------------------------------------------------------------------------
// Reply_To_Request_Surrender
//------------------------------------------------------------------------
function Reply_To_Request_Surrender returns boolean
params
  log_id:                    long
vars
  msg_sent:                  boolean := FALSE
  new_log_id:                long
  message_type:              long
  from_plr:                  long
  from_alliance:             long
  fear_towards_plr:          long
  pol_status:                long
  new_msg_type:              long
  alt_log_id:                long
  alt_msg_type:              long
  alt_plr:                   long
  perform_surrender:         boolean := TRUE
  should_surrender:          boolean := FALSE
  msg_text:                  string
begin

  // Get the message parameters
  set message_type := Sys_Empire_Log_Get_Log_Entry_Message_Type(sys_long_Player_ID, log_id)
  set from_plr := Sys_Empire_Log_Get_Log_Entry_Message_From_Player(sys_long_Player_ID, log_id)
  set from_alliance := Sys_Empire_Log_Get_Log_Entry_Message_From_Alliance(sys_long_Player_ID, log_id)

  // Prepare our reply
  set new_log_id := Sys_Empire_Politics_Create_Temporary_Message(sys_long_Player_ID)

  if (from_plr > 0) then
    call Sys_Empire_Politics_Set_Message_To_Empire(new_log_id, from_plr)
    // Debug output
    call Sys_Debug_Print("Politics", "  - Surrender Request from the " + Sys_Empire_Get_Empire_Name(from_plr))
  else
    call Sys_Empire_Politics_Set_Message_To_Alliance(new_log_id, from_alliance)
    // Debug output
    call Sys_Debug_Print("Politics", "  - Surrender Request from the " + Sys_Alliance_Get_Alliance_Name(from_alliance))
  endif

  // Set our reply's tone
  call Sys_Empire_Politics_Set_Message_Tone(new_log_id, Get_Message_Tone(from_plr, from_alliance))

  // Get our fear towards the player or alliance requesting our surrender
  if (from_plr > 0) then
    set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(from_plr)
    set pol_status := Sys_Empire_Politics_Get_Status_With_Player(sys_long_Player_ID, from_plr)
  else
    set fear_towards_plr := lst_Politics_Fear_Towards_Alliance.get(from_alliance)
    set pol_status := Sys_Empire_Politics_Get_Status_With_Alliance(sys_long_Player_ID, from_plr)
  endif

  // Should we surrender?
  if (fear_towards_plr < lng_Politics_Min_Fear_To_Surrender) then
    set perform_surrender := FALSE
  else
    set should_surrender := TRUE
  endif

  // Don't surrender if we are not at war
  if (pol_status <> POLITICAL_STATUS_TYPE_WAR) then
    set perform_surrender := FALSE
  endif

  // A random factor to not surrender based on our AI category
  if ((lng_AI_Categorization ^ 2) > Sys_Get_Random_Long(1, 25)) then
    set perform_surrender := FALSE
  endif

  // Don't surrender as easily if the player is the mega evil player
  if (perform_surrender) and (bool_Mega_Evil_Activated) then
    if Sys_Empire_Politics_Is_Player_The_Ultimate_Evil(sys_long_Player_ID, from_plr) then
      set perform_surrender := (Sys_Get_Random_Long(1, 4) = 1)
    endif
  endif

  // If we are a neutral player, don't give up as easily and don't give up to anyone but our best friend or main enemy
  if (perform_surrender) and (bool_Are_We_Neutral_Player) then
    if (from_plr = lng_Politics_Primary_Enemy) then
      set perform_surrender := (Sys_Get_Random_Long(1, 5) = 1)
    endif
    if (from_plr = lng_Politics_Primary_Friend) then
      set perform_surrender := (Sys_Get_Random_Long(1, 2) = 1)
    endif
  endif

  // Ministers should never surrender on the behalf of a human player!
  if (not Sys_Are_We_Computer_Player(sys_long_Player_ID)) then
    set perform_surrender := FALSE
  endif

  // Never surrender to human players if we are using AI team mode!
  if (from_plr > 0) and Sys_Is_Game_Using_Teams() then
    set perform_surrender := Sys_Empire_Politics_Is_Player_On_Our_Team(sys_long_Player_ID, from_plr)
  endif

  // Do not surrender if we are being asked repeatedly
  if (sys_long_Game_Date - lst_Date_Surrender_Last_Demanded.get(from_plr) < 10) then
    set perform_surrender := FALSE
  endif

  // Do we surrender?
  if (perform_surrender) then
    set new_msg_type := POLITICS_MSG_SURRENDER
    // Debug output
    call Sys_Debug_Print("Politics", "    - Accepted Surrender Request")
  else
    // Do not surrender
    set new_msg_type := POLITICS_MSG_REQUEST_REFUSE
    // Note the date of the surrender request
    call lst_Date_Surrender_Last_Demanded.set(from_plr, sys_long_Game_Date)
    // Debug output
    call Sys_Debug_Print("Politics", "    - Refused Surrender Request")
  endif

  // Consider surrendering to another player instead
  if (should_surrender) and (new_msg_type = POLITICS_MSG_REQUEST_REFUSE) then
    // Is the requesting empire's primary enemy a possibility?
    set alt_plr := Sys_Get_AI_Storage_Long(from_plr, 6, from_plr)
    // If not, select our best friend instead
    if (alt_plr = 0) and (lng_Politics_Primary_Friend > 0) and (lng_Politics_Primary_Friend <> from_plr) then
      set alt_plr := lng_Politics_Primary_Friend
    endif
    // Do we surrender to an alternate empire?
    if (alt_plr <> sys_long_Player_ID) then
      if Sys_Empire_Politics_Is_Player_Known(sys_long_Player_ID, alt_plr) then
        // Random chance that we surrender
        if (Sys_Get_Random_Long(1, 4) = 1) then
          set alt_log_id := Sys_Empire_Politics_Create_Temporary_Message(sys_long_Player_ID)
          set alt_msg_type := POLITICS_MSG_SURRENDER
          set msg_text := Get_Message_Text(alt_msg_type, message_type, alt_plr, 0, 0, 0, "", "", 0, 0)
          // Debug output
          call Sys_Debug_Print("Politics", "    - Surrendered to " + Sys_Empire_Get_Empire_Name(alt_plr) + " instead")
          // Send the message of our surrender
          call Sys_Empire_Politics_Set_Message_Tone(new_log_id, Get_Message_Tone(alt_plr, 0))
          call Sys_Empire_Politics_Set_Message_To_Empire(alt_log_id, alt_plr)
          call Sys_Empire_Politics_Set_Message_Type(alt_log_id, alt_msg_type)
          call Sys_Empire_Politics_Set_Message_Text(alt_log_id, msg_text)
          set msg_sent := Sys_Empire_Politics_Send_Message(alt_log_id)
          // Debug output
          call Sys_Debug_Print("Politics", "  - Sent a reply of " + Get_Message_Type(alt_msg_type) + " to the " Sys_Empire_Get_Empire_Name(alt_plr))
          call Sys_Debug_Print("Politics", "    - Message Text = " + msg_text)
        endif
      endif
    endif
  endif

  // Send our reply
  if (new_msg_type > 0) then
    set msg_text := Get_Message_Text(new_msg_type, message_type, from_plr, from_alliance, 0, 0, "", "", 0, 0)
    if (Sys_Length_String(msg_text) > 0) then
      call Sys_Empire_Politics_Set_Message_Type(new_log_id, new_msg_type)
      call Sys_Empire_Politics_Set_Message_Text(new_log_id, msg_text)
      set msg_sent := Sys_Empire_Politics_Send_Message(new_log_id)
      // Debug output
      call Sys_Debug_Print("Politics", "  - Sent a reply of " + Get_Message_Type(new_msg_type) + " to the " Sys_Empire_Get_Empire_Name(from_plr))
      call Sys_Debug_Print("Politics", "    - Message Text = " + msg_text)
    endif
  endif
  
  return msg_sent
end

//------------------------------------------------------------------------
// Get_Gift_Items_To_Request
//------------------------------------------------------------------------
function Get_Gift_Items_To_Request returns boolean
params
  new_log_id:                long
  to_plr:                    long
vars
  lst_item_type:             longlist
  lst_item_id:               longlist
  lst_item_amount:           longlist
  list_count:                long
  list_index:                long
  item_type:                 long
  item_id:                   long
  item_amount:               long
  sel_item_type:             long
  lst_sel_items:             longlist
  pick:                      long
  max_gift_value:            long
  cur_gift_value:            long
  pct_compare:               long
  fear_towards_plr:          long
  is_enemy:                  boolean
  gift_items_added:          boolean := TRUE
begin

  // Get our fear level towards the player
  set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(to_plr)

  // Set the value of the gift we want
  if (fear_towards_plr < 0) then
    set max_gift_value := Sys_Get_Random_Long(5000, 10000) + (500 * fear_towards_plr)
  else
    set max_gift_value := Sys_Get_Random_Long(5000, 10000)
  endif

  // Determine the items we want
  loop
    set item_id := 0
    set item_amount := 0
    set pick := Sys_Get_Random_Long(1, 7)

    case pick
      1:
        // System
        if (fear_towards_plr < -50) then
          set item_type := MESSAGE_PACKAGE_ITEM_TYPE_SYSTEM
        endif
      2:
        // Planet
        if (fear_towards_plr < -25) then
          set item_type := MESSAGE_PACKAGE_ITEM_TYPE_PLANET
        endif
      3:
        // Resources
        if (bool_Race_Minerals_Low) or (bool_Race_Minerals_Adequate) or (bool_Race_Organics_Low) or (bool_Race_Organics_Adequate) or (bool_Race_Radioactives_Low) or (bool_Race_Radioactives_Adequate) or (bool_Race_Maintenance_High) then
          set item_type := MESSAGE_PACKAGE_ITEM_TYPE_RESOURCE
          set item_amount := Sys_Get_Random_Long(1, 5) * 1000
        endif
      4:
        // Technology
        set item_type := MESSAGE_PACKAGE_ITEM_TYPE_TECHNOLOGY
      5:
        // Ship
        set item_type := MESSAGE_PACKAGE_ITEM_TYPE_SHIP
      6:
        // Star Charts
        set item_type := MESSAGE_PACKAGE_ITEM_TYPE_STARCHART
      7:
        // Communications Channel
        set item_type := MESSAGE_PACKAGE_ITEM_TYPE_COMM
    endcase

    // Add the item to our list
    if (item_type > 0) then
      // Make a list of possible objects for the selected item type
      call Sys_Empire_Log_Get_Package_Selection_List(ENTITY_TYPE_EMPIRE, to_plr, ENTITY_TYPE_EMPIRE, sys_long_Player_ID, lst_sel_items, item_type, TRUE, FALSE)
      // Choose one item from the object list
      if (lst_sel_items.count() > 0) then
        set pick := Sys_Get_Random_Long(1, lst_sel_items.count())
        set item_id := lst_sel_items.get(pick)
      endif
      // Add the requested item to the gift package
      if (item_id > 0) then
        call Sys_Empire_Log_Add_Package_Items(new_log_id, PACKAGE_TYPE_GET, item_type, item_id, item_amount)
        // Update the total gift value
        set cur_gift_value := Calculate_Package_Value(new_log_id, PACKAGE_TYPE_GET, to_plr)
      endif
    endif
    exitwhen (cur_gift_value >= max_gift_value)
  endloop

  if (cur_gift_value <= 0) then
    set gift_items_added := FALSE
  endif

  return gift_items_added
end

//------------------------------------------------------------------------
// Reply_To_Request_Gift
//------------------------------------------------------------------------
function Reply_To_Request_Gift returns boolean
params
  log_id:                    long
vars
  msg_sent:                  boolean := FALSE
  give_gift:                 boolean
  fear_towards_plr:          long
  new_log_id:                long
  message_type:              long
  from_plr:                  long
  from_alliance:             long
  new_msg_type:              long
  is_enemy:                  boolean
  msg_text:                  string
begin

  // Get the message parameters
  set message_type := Sys_Empire_Log_Get_Log_Entry_Message_Type(sys_long_Player_ID, log_id)
  set from_plr := Sys_Empire_Log_Get_Log_Entry_Message_From_Player(sys_long_Player_ID, log_id)
  set from_alliance := Sys_Empire_Log_Get_Log_Entry_Message_From_Player(sys_long_Player_ID, log_id)

  // Note our anger towards the requesting player or alliance
  if (from_plr > 0) then
    set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(from_plr)
    set is_enemy := Sys_Empire_Politics_Is_Player_Enemy(sys_long_Player_ID, from_plr)
    // Debug output
    call Sys_Debug_Print("Politics", "  - Gift Requested from the " + Sys_Empire_Get_Empire_Name(from_plr))
  else
    set fear_towards_plr := lst_Politics_Fear_Towards_Alliance.get(from_alliance)
    set is_enemy := Sys_Empire_Politics_Is_Alliance_Enemy(sys_long_Player_ID, from_alliance)
    // Debug output
    call Sys_Debug_Print("Politics", "  - Gift Requested from the " + Sys_Alliance_Get_Alliance_Name(from_alliance))
  endif

  // Prepare our reply
  set new_log_id := Sys_Empire_Politics_Create_Temporary_Message(sys_long_Player_ID)
  if (from_plr > 0) then
    call Sys_Empire_Politics_Set_Message_To_Empire(new_log_id, from_plr)
  else
    call Sys_Empire_Politics_Set_Message_To_Alliance(new_log_id, from_alliance)
  endif
  call Sys_Empire_Politics_Set_Message_Tone(new_log_id, Get_Message_Tone(from_plr, from_alliance))

  // Should we give a gift?
  if (is_enemy) then
    set give_gift := (fear_towards_plr >= lng_Politics_Min_Fear_To_Give_Enemy_Gift)
  else
    set give_gift := (fear_towards_plr >= lng_Politics_Min_Fear_To_Give_Friend_Gift)
  endif

  // Random factor not to give the gift based on our AI category
  if (give_gift) and (Sys_Get_Random_Long(1, 1 + lng_AI_Categorization) = 1) then
    set give_gift := FALSE
  endif
  
  // Don't give a gift to human players when using AI team mode!
  if (from_plr > 0) and Sys_Is_Game_Using_Teams() then
    set give_gift := (not Sys_Empire_Politics_Is_Player_On_Our_Team(sys_long_Player_ID, from_plr))
  endif

  // Do we give the gift?
  if (give_gift) then
    set new_msg_type := POLITICS_MSG_GIVE_GIFT
    // Debug output
    call Sys_Debug_Print("Politics", "    - Accepted Gift Request")
  else
    set new_msg_type := POLITICS_MSG_REQUEST_REFUSE
    // Debug output
    call Sys_Debug_Print("Politics", "    - Refused Gift Request")
  endif

  // Send our reply
  if (new_msg_type > 0) then
    set msg_text := Get_Message_Text(new_msg_type, message_type, from_plr, from_alliance, 0, 0, "", "", 0, 0)
    if (Sys_Length_String(msg_text) > 0) then
      if Get_Gift_To_Give(log_id, new_log_id) then
        call Sys_Empire_Politics_Set_Message_Type(new_log_id, new_msg_type)
        call Sys_Empire_Politics_Set_Message_Text(new_log_id, msg_text)
        set msg_sent := Sys_Empire_Politics_Send_Message(new_log_id)
        // Debug output
        call Sys_Debug_Print("Politics", "  - Sent a reply of " + Get_Message_Type(new_msg_type) + " to the " Sys_Empire_Get_Empire_Name(from_plr))
        call Sys_Debug_Print("Politics", "    - Message Text = " + msg_text)
      endif
    endif
  endif
  
  return msg_sent
end

//------------------------------------------------------------------------
// Get_Gift_To_Give
//------------------------------------------------------------------------
function Get_Gift_To_Give returns boolean
params
  log_id:                    long
  new_log_id:                long
vars
  lst_item_type:             longlist
  lst_item_id:               longlist
  lst_item_amount:           longlist
  list_count:                long
  list_index:                long
  item_type:                 long
  item_id:                   long
  item_amount:               long
  sel_item_type:             long
  to_plr:                    long
  to_alliance:               long
  lst_sel_items:             longlist
  pick:                      long
  max_gift_value:            long
  cur_gift_value:            long
  fear_towards_plr:          long
  is_enemy:                  boolean
  gift_items_added:          boolean := TRUE
begin

  // Get the message parameters
  set to_plr := Sys_Empire_Log_Get_Log_Entry_Message_From_Player(sys_long_Player_ID, log_id)
  set to_alliance := Sys_Empire_Log_Get_Log_Entry_Message_From_Alliance(sys_long_Player_ID, log_id)

  // Note our fear towards the selected player or alliance
  if (to_plr > 0) then
    set is_enemy := Sys_Empire_Politics_Is_Player_Enemy(sys_long_Player_ID, to_plr)
    set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(to_plr)
  else
    set is_enemy := Sys_Empire_Politics_Is_Alliance_Enemy(sys_long_Player_ID, to_alliance)
    set fear_towards_plr := lst_Politics_Fear_Towards_Alliance.get(to_alliance)
  endif

  // Increase our gift value based on our fear of the requesting player
  set max_gift_value := 5000 + (fear_towards_plr * 500)

  // Get the list of items
  call Sys_Empire_Log_Get_Package_Items(sys_long_Player_ID, log_id, PACKAGE_TYPE_GET, lst_item_type, lst_item_id, lst_item_amount)
  set list_count := lst_item_type.count()

  if (list_count > 0) then
    for list_index := 1 to list_count do
      // Don't add more items then we want to give in the gift package
      if (cur_gift_value < max_gift_value) then
        set item_type := lst_item_type.get(list_index)
        set item_id := lst_item_id.get(list_index)
        set item_amount := lst_item_amount.get(list_index)
        set sel_item_type := 0
        // Convert 'Any' items to specific items
        case item_type
          MESSAGE_PACKAGE_ITEM_TYPE_ANY_PLANET:
            set sel_item_type := MESSAGE_PACKAGE_ITEM_TYPE_PLANET
          MESSAGE_PACKAGE_ITEM_TYPE_ANY_TECHNOLOGY:
            set sel_item_type := MESSAGE_PACKAGE_ITEM_TYPE_TECHNOLOGY
          MESSAGE_PACKAGE_ITEM_TYPE_ANY_SHIP:
            set sel_item_type := MESSAGE_PACKAGE_ITEM_TYPE_SHIP
          MESSAGE_PACKAGE_ITEM_TYPE_ANY_STARCHART:
            set sel_item_type := MESSAGE_PACKAGE_ITEM_TYPE_STARCHART
          MESSAGE_PACKAGE_ITEM_TYPE_ANY_COMM:
            set sel_item_type := MESSAGE_PACKAGE_ITEM_TYPE_COMM
        endcase
        // Get a list of possible objects for the 'Any' item type
        if (sel_item_type > 0) then
          if (to_plr > 0) then
            call Sys_Empire_Log_Get_Package_Selection_List(ENTITY_TYPE_EMPIRE, sys_long_Player_ID, ENTITY_TYPE_EMPIRE, to_plr, lst_sel_items, sel_item_type, TRUE, FALSE)
          else
            call Sys_Empire_Log_Get_Package_Selection_List(ENTITY_TYPE_EMPIRE, sys_long_Player_ID, ENTITY_TYPE_ALLIANCE, to_alliance, lst_sel_items, sel_item_type, TRUE, FALSE)
          endif
          // Randomly pick one of the items to give
          if (lst_sel_items.count() > 0) then
            // Add the selected item to the gift package
            set pick := Sys_Get_Random_Long(1, lst_sel_items.count())
            call Sys_Empire_Log_Add_Package_Items(new_log_id, PACKAGE_TYPE_GIVE, sel_item_type, lst_sel_items.get(pick), 0)
          endif
        else
          // Add the specific item to the package
          if (item_id > 0) then
            call Sys_Empire_Log_Add_Package_Items(new_log_id, PACKAGE_TYPE_GIVE, item_type, item_id, item_amount)
          endif
        endif
        // Update the total gift package value
        set cur_gift_value := Calculate_Package_Value(new_log_id, PACKAGE_TYPE_GIVE, to_plr)
      endif
    endfor
  endif

  if (cur_gift_value <= 0) then
    set gift_items_added := FALSE
  endif

  return gift_items_added
end

//------------------------------------------------------------------------
// Reply_To_General_Request
//------------------------------------------------------------------------
function Reply_To_General_Request returns boolean
params
  log_id:                    long
vars
  msg_sent:                  boolean := FALSE
  accept_demand:             boolean := TRUE
  fear_towards_req:          long
  fear_towards_other:        long
  new_log_id:                long
  msg_type:                  long
  from_plr:                  long
  from_alliance:             long
  from_name:                 string
  other_plr:                 long
  other_alliance:            long
  other_name:                string
  new_msg_type:              long
  total_requests:            long
  list_count:                long
  list_index:                long
  target_sobj_id:            long
  target_system_id:          long
  is_req_friend:             boolean
  is_other_friend:           boolean
  is_req_enemy:              boolean
  is_other_enemy:            boolean
  is_req_enemy_of_other:     boolean
  is_req_mut_def_partner:    boolean
  msg_text:                  string
  alt_msg_text:              string
begin

  // Get the message's parameters
  set msg_type := Sys_Empire_Log_Get_Log_Entry_Message_Type(sys_long_Player_ID, log_id)
  set from_plr := Sys_Empire_Log_Get_Log_Entry_Message_From_Player(sys_long_Player_ID, log_id)
  set from_alliance := Sys_Empire_Log_Get_Log_Entry_Message_From_Alliance(sys_long_Player_ID, log_id)
  set other_plr := Sys_Empire_Log_Get_Log_Entry_Message_Param_Against_Player(sys_long_Player_ID, log_id)
  set other_alliance := Sys_Empire_Log_Get_Log_Entry_Message_Param_Against_Alliance(sys_long_Player_ID, log_id)
  set target_sobj_id := Sys_Empire_Log_Get_Log_Entry_Message_Param_Target_Space_Object_ID(sys_long_Player_ID, log_id)
  set target_system_id := Sys_Empire_Log_Get_Log_Entry_Message_Param_Target_System(sys_long_Player_ID, log_id)

  // Prepare our reply
  set new_log_id := Sys_Empire_Politics_Create_Temporary_Message(sys_long_Player_ID)
  call Sys_Empire_Politics_Set_Message_To_Empire(new_log_id, from_plr)
  call Sys_Empire_Politics_Set_Message_Tone(new_log_id, Get_Message_Tone(from_plr, from_alliance))

  // Get our fear, friendship, and generally standing versus the requesting player or alliance
  if (from_plr > 0) then
    set from_name := Sys_Empire_Get_Empire_Name(from_plr)
    set is_req_friend := (lst_Politics_Friendship_Towards_Player.get(from_plr) > 5)
    set is_req_enemy := Sys_Empire_Politics_Is_Player_Enemy(sys_long_Player_ID, from_plr)
    set is_req_mut_def_partner := Do_We_Have_Treaty_Element_With_Player(from_plr, TREATY_ELEMENT_TYPE_MUTUAL_DEFENSE_PACT, FALSE, 0)
    set fear_towards_req := lst_Politics_Fear_Towards_Player.get(from_plr)
  else
    set from_name := Sys_Alliance_Get_Alliance_Name(from_alliance)
    set is_req_friend := Sys_Empire_Politics_Is_Alliance_Ally(sys_long_Player_ID, from_alliance)
    set is_req_enemy := Sys_Empire_Politics_Is_Alliance_Enemy(sys_long_Player_ID, from_alliance)
    set is_req_mut_def_partner := FALSE
    set fear_towards_req := lst_Politics_Fear_Towards_Alliance.get(from_alliance)
  endif

  // Debug output
  call Sys_Debug_Print("Politics", "  - Request from " + from_name)

  // If applicable, get the other player's attributes
  if (other_plr > 0) then
    set other_name := Sys_Empire_Get_Empire_Name(other_plr)
    set is_other_friend := (lst_Politics_Friendship_Towards_Player.get(other_plr) > 5)
    set is_other_enemy := Is_Player_Enemy(sys_long_Player_ID, other_plr, TRUE)
    set is_req_enemy_of_other := Is_Player_Enemy(from_plr, other_plr, TRUE)
    set fear_towards_other := lst_Politics_Fear_Towards_Player.get(other_plr)
  endif

  //  If applicable, get the other alliance's attributes
  if (other_alliance > 0) then
    set other_name := Sys_Alliance_Get_Alliance_Name(other_alliance)
    set is_other_friend := Sys_Empire_Politics_Is_Alliance_Ally(sys_long_Player_ID, other_alliance)
    set is_other_enemy := Sys_Empire_Politics_Is_Alliance_Enemy(sys_long_Player_ID, other_alliance)
    set is_req_enemy_of_other := Sys_Empire_Politics_Is_Alliance_Enemy(from_plr, other_alliance)
    set fear_towards_other := lst_Politics_Fear_Towards_Alliance.get(other_alliance)
  endif

  // Do we accept the demand?
  if (is_req_enemy) then
    set accept_demand := (fear_towards_req >= lng_Politics_Min_Fear_To_Accept_Enemy_Demand)
  else
    set accept_demand := (fear_towards_req >= lng_Politics_Min_Fear_To_Accept_Friend_Demand)
  endif

  // Special requests from players only
  // Request declare war on empire
  if (msg_type = POLITICS_MSG_REQUEST_DECLARE_WAR_ON_EMPIRE) then
    set accept_demand := FALSE
    // Make sure the requesting player is actually at war with the other empire
    if (is_req_friend) then
      if (is_other_enemy) then
        // Don't accept the request if we are already at war with the specified empire
        set accept_demand := FALSE
        // Message text
        if (Sys_Get_Random_Long(1, 2) = 1) then
          set alt_msg_text := "We are already at war with the " + other_name + ". Do not waste our time by sending thoughtless requests."
        else
          set alt_msg_text := "The " + from_name + " must pay more attention to the state of the galaxy. We are already at war with the " + other_name + "."
        endif
      else
        // Consider declaring war if the specified empire is not our enemy
        if (is_req_enemy_of_other) then
          // Consider declaring war because of a Mutual Defense Pact
          if (is_req_mut_def_partner) then
            if (is_other_friend) then
              // Don't accept if we are friends with the specified empire
              set accept_demand := FALSE
              // Message text
              if (Sys_Get_Random_Long(1, 2) = 1) then
                set alt_msg_text := "We cannot go to war with the " + other_name + " despite our Mutual Defense Pact. You will need to resolve your differences with them on your own."
              else
                set alt_msg_text := "It is not possible to declare war on the " + other_name + " because of our existing treaty with them. We do not wish to dishonor our own agreement, so perhaps we can resolve the differences between the " + from_name + " and the " + other_name + "?"
              endif
            else
              // Accept the demand (in general) but reserve the right to check if we can handle war the specified empire
              set accept_demand := TRUE
              // Message text
              if (Sys_Get_Random_Long(1, 2) = 1) then
                set alt_msg_text := "The reasons for war with the " + other_name + " are strong and we would like to honor our agreement, but we must explore if we are capable to wage such a war."
              else
                set alt_msg_text := "We feel obligated to honor our defense pact with the " + from_name + ", but first we must determine if we can handle the requirements of a war with the vile " + other_name + "."
              endif
            endif
          else
            // Don't accept the demand because we don't have a Mutual Defense Pact with the requesting empire
            set accept_demand := FALSE
            // Message text
            if (Sys_Get_Random_Long(1, 2) = 1) then
              set alt_msg_text := "There might be reasons to justify war with the " + other_name + ", but we cannot take that risk to find out if they are the right ones."
            else
              set alt_msg_text := "The " + from_name + " are certainly our friends, but we cannot simply go to war against the " + other_name + " for this reason alone."
            endif
          endif
        else
          // Don't accept if the requesting empire is not even at war with the specified empire
          set accept_demand := FALSE
          // Message text
          if (Sys_Get_Random_Long(1, 2) = 1) then
            set alt_msg_text := "Do not expect us to declare war on the " + other_name + " if you are not willing to do the same."
          else
            set alt_msg_text := "Do you think we are foolish enough to considering war with the " + other_name + " on your whim? The bidding of the " + from_name + " can be done by themselves."
          endif
        endif
      endif
    endif
  endif

  // Military support against our enemies
  if (msg_type = POLITICS_MSG_REQUEST_MILITARY_ASSISTANCE_AGAINST_EMPIRE) then
    set accept_demand := FALSE
    // Is the request from our friend?
    if (is_req_friend) then
      if (is_other_enemy) then
        // Accept the request if we are at war with the specified target empire
        set accept_demand := TRUE
        // Message text
        if (Sys_Get_Random_Long(1, 2) = 1) then
          set alt_msg_text := "You don't need really need to ask us, but we will continue to engage the " + other_name + " as much as we can."
        else
          set alt_msg_text := "We are already at war with the " + other_name + " and we will continue to fight them."
        endif
      else
        // Is the target empire our friend?
        if (is_other_friend) then
          // Reject the request if the specified target empire is our friend
          set accept_demand := FALSE
          // Message text
          if (Sys_Get_Random_Long(1, 2) = 1) then
            set alt_msg_text := "The " + other_name + " maintain a treaty with us. We do not desire to break it."
          else
            set alt_msg_text := "Why does the " + from_name + " ask us to attack our treaty partners?"
          endif
        else
          // Message text
          if (Sys_Get_Random_Long(1, 2) = 1) then
            set alt_msg_text := "Now is not a good time for us to attack the " + other_name + "."
          else
            set alt_msg_text :=  "We are busy enough with our own troubles. You can deal with the " + other_name + " for now."
          endif
        endif
      endif
    endif
  endif

  // Military support in a specific system
  if (msg_type = POLITICS_MSG_REQUEST_MILITARY_ASSISTANCE_IN_SYSTEM) then
    set accept_demand := FALSE
    // Is the requesting empire our friend?
    if (is_req_friend) then
      if (is_other_enemy) then
        if Do_We_Have_Colonies_In_Adjacent_Systems(target_system_id) then
          // Accept the demand and add it to our list of systems to follow up requests in
          set accept_demand := TRUE
          call lst_AI_Request_Location_System.add(target_system_id)
          // Message Text
          if (Sys_Get_Random_Long(1, 2) = 1) then
            set alt_msg_text := "We will attempt to attack the " + other_name + " in the " + Sys_Get_Solar_System_Name(target_system_id) " system if we can spare the forces."
          else
            set alt_msg_text := "The " + Sys_Get_Solar_System_Name(target_system_id) + " is close to our territory. We will attempt to move our forces there if we have enough ships available."
          endif
        else
          // We are not close enough for an attack
          set accept_demand := FALSE
          // Message text
          if (Sys_Get_Random_Long(1, 2) = 1) then
            set alt_msg_text := "Our available fleets are simply out of range to attack the " + other_name + " in the " Sys_Get_Solar_System_Name(target_system_id) + " system."
          else
            set alt_msg_text := "It is not possible for us to attack the " + other_name + " in the " Sys_Get_Solar_System_Name(target_system_id) + " system. The target system is just too far."
          endif
        endif
      else
        // Reject the demand as the specified target empire is our friend
        set accept_demand := FALSE
        // Message text
        if (Sys_Get_Random_Long(1, 2) = 1) then
          set alt_msg_text := "We have a treaty with the " + other_name + " and are not willing to attack them on behalf of the " + from_name + "."
        else
          set alt_msg_text := "What you are request is impossible. We maintain a treaty with the " + other_name + " and will not attack them. Do not make this request of us again."
        endif
      endif
    endif
  endif

  // Economic Assistance
  if (is_req_friend) and (msg_type = POLITICS_MSG_REQUEST_ECONOMIC_ASSISTANCE) then
    if (bool_Race_Minerals_Surplus) and (bool_Race_Organics_Surplus) and (bool_Race_Radioactives_Surplus) then
      set accept_demand := TRUE
      call Sys_Empire_Log_Add_Package_Items(new_log_id, PACKAGE_TYPE_GIVE, MESSAGE_PACKAGE_ITEM_TYPE_RESOURCE, 0, 10000)
    endif
  endif

  // Research Support (Pending)

  // Intelligence support
  if (is_req_friend) and (msg_type = POLITICS_MSG_REQUEST_INTELLIGENCE_ASSISTANCE_AGAINST_EMPIRE) then
    if (is_other_enemy) and (bool_Enemy_Behind_In_Intel) then
      set accept_demand := TRUE
    endif
  endif

  // Deny the request on occasion based on our AI category
  if (accept_demand) and (lng_AI_Categorization > Sys_Get_Random_Long(1, 10)) then
    set accept_demand := FALSE
  endif

  // Deny the request if the demanding player or alliance has already made a number of requests
  if (accept_demand) then
    set list_count := lst_Requests_From_Plr.count()
    if (list_count > 0) then 
      for list_index := 1 to list_count do
        if ((from_plr > 0) and (lst_Requests_From_Plr.get(list_index) = from_plr)) or ((from_alliance > 0) and (lst_Requests_From_Alliance.get(list_index) = from_alliance)) then
          set total_requests := total_requests + 1
        endif
      endfor
    endif
    if (total_requests > lng_Politics_Max_Concurrent_Requests_To_Honor_From_One_Player) then
      set accept_demand := FALSE
      set alt_msg_text := "You have asked us too many times."
    endif
  endif

  // Accept the demand if its from a player on our team
  if (from_plr > 0) and Sys_Is_Game_Using_Teams() then
    set accept_demand := Sys_Empire_Politics_Is_Player_On_Our_Team(sys_long_Player_ID, from_plr)
  endif

  // Accept or refuse the request
  if (accept_demand) then
    set new_msg_type := POLITICS_MSG_REQUEST_ACCEPT
    // Add the request to our list of requests
    call Perform_Message_Demand(log_id)
    // Debug output
    call Sys_Debug_Print("Politics", "    - Accepted Request")
  else
    set new_msg_type := POLITICS_MSG_REQUEST_REFUSE
    // Debug output
    call Sys_Debug_Print("Politics", "    - Refused Request")
  endif

  // Send our reply
  if (new_msg_type > 0) then
    set msg_text := Get_Message_Text(new_msg_type, msg_type, from_plr, from_alliance, other_plr, other_alliance, "", "", target_system_id, target_sobj_id)
    // Change the message text if there is alternative text
    if (alt_msg_text <> "") then
      set msg_text := alt_msg_text
    endif
    // Compose and send our message
    if (msg_text > 0) then
      // Do we have anything thing to add?
      call Sys_Empire_Politics_Set_Message_Type(new_log_id, new_msg_type)
      call Sys_Empire_Politics_Set_Message_Text(new_log_id, msg_text)
      set msg_sent := Sys_Empire_Politics_Send_Message(new_log_id)
      // Debug output
      if (from_plr > 0) then
        call Sys_Debug_Print("Politics", "  - Sent a reply of " + Get_Message_Type(new_msg_type) + " to the " Sys_Empire_Get_Empire_Name(from_plr))
        call Sys_Debug_Print("Politics", "    - Message Text = " + msg_text)
      else
        // Debug output
        call Sys_Debug_Print("Politics", "  - Sent a reply of " + Get_Message_Type(new_msg_type) + " to the " Sys_Alliance_Get_Alliance_Name(from_alliance))
        call Sys_Debug_Print("Politics", "    - Message Text = " + msg_text)
      endif
    endif
  endif

  return msg_sent
end

//------------------------------------------------------------------------
// Perform_Message_Demand
//------------------------------------------------------------------------
function Perform_Message_Demand returns boolean
params
  log_id:                    long
vars
  message_type:              long
  from_plr:                  long
  from_alliance:             long
  target_plr:                long
  target_alliance:           long
  target_system:             long
  target_sobj_id:            long
begin

  // Get the message parameters
  set message_type := Sys_Empire_Log_Get_Log_Entry_Message_Type(sys_long_Player_ID, log_id)
  set from_plr := Sys_Empire_Log_Get_Log_Entry_Message_From_Player(sys_long_Player_ID, log_id)
  set from_alliance := Sys_Empire_Log_Get_Log_Entry_Message_From_Alliance(sys_long_Player_ID, log_id)

  // Get the request's parameters
  set target_plr := Sys_Empire_Log_Get_Log_Entry_Message_Param_Against_Player(sys_long_Player_ID, log_id)
  set target_alliance := Sys_Empire_Log_Get_Log_Entry_Message_Param_Against_Alliance(sys_long_Player_ID, log_id)
  set target_system := Sys_Empire_Log_Get_Log_Entry_Message_Param_Target_System(sys_long_Player_ID, log_id)
  set target_sobj_id := Sys_Empire_Log_Get_Log_Entry_Message_Param_Target_Space_Object_ID(sys_long_Player_ID, log_id)

  // Add it to our list of requests
  call lst_Requests_Type.add(message_type)
  call lst_Requests_From_Plr.add(from_plr)
  call lst_Requests_From_Alliance.add(from_plr)
  call lst_Requests_Date.add(sys_long_Game_Date)
  call lst_Requests_Target_Plr.add(target_plr)
  call lst_Requests_Target_Alliance.add(target_alliance)
  call lst_Requests_Target_Sys.add(target_system)
  call lst_Requests_Target_Sobj.add(target_sobj_id)

  // Note the type of request
  case (message_type)
    POLITICS_MSG_REQUEST_STOP_AGGRESSION_AGAINST_EMPIRE:
      call lst_AI_Temp_Stop_Attack_vs_Empire.add(target_plr)
    POLITICS_MSG_REQUEST_BREAK_TREATY_WITH_EMPIRE:
      // Ok
    POLITICS_MSG_REQUEST_DECLARE_WAR_ON_EMPIRE:
      // Ok
    POLITICS_MSG_REQUEST_MAKE_PEACE_WITH_EMPIRE:
      // Ok
    POLITICS_MSG_REQUEST_EMPIRE_BREAK_WITH_ALLIANCE:
      // Ok
    POLITICS_MSG_REQUEST_EMPIRE_JOIN_WITH_ALLIANCE:
      // Ok
    POLITICS_MSG_REQUEST_STOP_ESPIONAGE_AGAINST_US:
      call lst_AI_Temp_Stop_Intel_vs_Empire.add(from_plr)
    POLITICS_MSG_REQUEST_STOP_ESPIONAGE_AGAINST_EMPIRE:
      call lst_AI_Temp_Stop_Intel_vs_Empire.add(target_plr)
    POLITICS_MSG_REQUEST_STOP_SABOTAGE_AGAINST_US:
      call lst_AI_Temp_Stop_Intel_vs_Empire.add(from_plr)
    POLITICS_MSG_REQUEST_STOP_SABOTAGE_AGAINST_EMPIRE:
      call lst_AI_Temp_Stop_Intel_vs_Empire.add(target_plr)
    POLITICS_MSG_REQUEST_STOP_SHIP_ATTACKS_IN_SYSTEM:
      call lst_AI_Temp_Stop_Attack_in_System.add(target_system)
    POLITICS_MSG_REQUEST_MILITARY_ASSISTANCE:
      call lst_AI_Give_Military_Assistance_vs_Empire.add(target_plr)
    POLITICS_MSG_REQUEST_MILITARY_ASSISTANCE_AGAINST_EMPIRE:
      call lst_AI_Give_Military_Assistance_vs_Empire.add(target_plr)
    POLITICS_MSG_REQUEST_MILITARY_ASSISTANCE_IN_SYSTEM:
      call lst_AI_Give_Military_Assistance_In_System.add(target_system)
    POLITICS_MSG_REQUEST_ECONOMIC_ASSISTANCE:
      call lst_AI_Give_Resource_Assistance_To_Empire.add(from_plr)
    POLITICS_MSG_REQUEST_TECHNOLOGICAL_ASSISTANCE:
      call lst_AI_Give_Technological_Assistance_To_Empire.add(from_plr)
    POLITICS_MSG_REQUEST_INTELLIGENCE_ASSISTANCE:
      call lst_AI_Give_Intel_Def_Assistance_To_Empire.add(from_plr)
    POLITICS_MSG_REQUEST_INTELLIGENCE_ASSISTANCE_AGAINST_EMPIRE:
      call lst_AI_Give_Intel_Atk_Assistance_To_Empire.add(from_plr)
    POLITICS_MSG_REQUEST_STOP_BORDER_INCURSIONS:
      call lst_AI_Remove_Ships_From_System.add(target_system)
    POLITICS_MSG_REQUEST_STOP_MILITARY_ATTACKS_ON_US:
      call lst_AI_Temp_Stop_Attack_vs_Empire.add(from_plr)
    POLITICS_MSG_REQUEST_STOP_MILITARY_ATTACKS_AGAINST_EMPIRE:
      call lst_AI_Temp_Stop_Attack_vs_Empire.add(target_plr)
    POLITICS_MSG_REQUEST_REMOVE_SHIPS_FROM_SYSTEM:
      call lst_AI_Remove_Ships_From_System.add(target_system)
    POLITICS_MSG_REQUEST_REMOVE_COLONIES_FROM_SYSTEM:
      // Pending
  endcase

  return TRUE
end

//------------------------------------------------------------------------
// Is_Specific_Request
//------------------------------------------------------------------------
function Is_Specific_Request returns boolean
params
  msg_type:                  long
  target_id:                 long
  alliance_id:               long
vars
  found_request:             boolean := FALSE
  list_count:                long
  list_index:                long
begin

  // Find a specific request
  set list_count := lst_Requests_Type.count()

  if (list_count > 0) then
    set list_index := 0
    loop
      set list_index := list_index + 1
      if (lst_Requests_Type.get(list_index) = msg_type) then
        if ((target_id > 0) and (lst_Requests_Target_Plr.get(list_index) = target_id)) or ((alliance_id > 0) and (lst_Requests_Target_Alliance.get(list_index) = alliance_id)) then
          set found_request := TRUE
        endif
      endif
      exitwhen (list_index >= list_count) or (found_request)
    endloop
  endif

  return found_request
end

//------------------------------------------------------------------------
// Send_Messages
//------------------------------------------------------------------------
function Send_Messages returns boolean
vars
  plr_count:                 long
  plr_index:                 long
  alliance_count:            long
  alliance_index:            long
  our_alliance:              long
  their_alliance:            long
  pol_status:                long
  pol_status_time:           long
  last_treaty_date:          string
  last_request_date:         string
  last_request_type:         string
  last_broken_date:          string
  num_broken_treaties:       string
  debug_str:                 string
begin

  // Note our alliance if we are in one
  set our_alliance := Sys_Empire_Politics_In_Alliance_ID(sys_long_Player_ID)

  // Send messages to other players
  set plr_count := Sys_Get_Number_Of_Players()

  if (plr_count > 0) then
    for plr_index := 1 to plr_count do
      if (plr_index <> sys_long_Player_ID) and (Sys_Empire_Politics_Is_Player_Known(sys_long_Player_ID, plr_index)) then
        // Note our political status
        set pol_status := Sys_Empire_Politics_Get_Status_With_Player(sys_long_Player_ID, plr_index)
        set pol_status_time := Sys_Empire_Politics_Get_Status_Time_With_Player(sys_long_Player_ID, plr_index)
        // Debug output
        case pol_status
          POLITICAL_STATUS_TYPE_KNOWN:
            set debug_str := " (Known; No Treaty):"
          POLITICAL_STATUS_TYPE_TREATY:
            set debug_str := " (Treaty = " + Sys_Empire_Politics_Get_Treaty_Name_Between_Players(sys_long_Player_ID, plr_index) + "):"
          POLITICAL_STATUS_TYPE_WAR:
            set debug_str := " (War):"
        endcase
        // Note last treaty and request dates
        set last_treaty_date := Sys_Convert_Long_To_String(lst_Date_Treaty_Last_Offered.get(plr_index))
        set last_request_date := Sys_Convert_Long_To_String(lst_Date_Last_Request_Made.get(plr_index))
        set last_request_type := Get_Message_Type(lst_Last_Request_Made_Type.get(plr_index))
        set last_broken_date := Sys_Convert_Long_To_String(lst_Date_Last_Treaty_Broken.get(plr_index))
        set num_broken_treaties := Sys_Convert_Long_To_String(lst_Num_Times_Treaty_Broken.get(plr_index))
        // Debug output
        call Sys_Debug_Print("Politics", "------")
        call Sys_Debug_Print("Politics", "  - Diplomacy with "+ Sys_Empire_Get_Empire_Name(plr_index) + debug_str)
        call Sys_Debug_Print("Politics", "    - Current Status Time = " + Sys_Convert_Long_To_String(pol_status_time))
        call Sys_Debug_Print("Politics", "    - Last Treaty Offered to them = " + last_treaty_date)
        call Sys_Debug_Print("Politics", "    - Last Message Made to them = " + last_request_date)
        call Sys_Debug_Print("Politics", "    - Last Message Type to them = " + last_request_type)
        call Sys_Debug_Print("Politics", "    - Last Broken Treaty by them = " + last_broken_date)
        call Sys_Debug_Print("Politics", "    - Number of Broken Treaties by them = " + num_broken_treaties)
        // If we haven't sent a message, consider sending one
        if (lst_Message_Sent_To_Player.get(plr_index) = 0) then
          set their_alliance := Sys_Empire_Politics_In_Alliance_ID(plr_index)
          if (their_alliance = 0) then
            // Debug output
            call Sys_Debug_Print("Politics", "    ------")
            call Sys_Debug_Print("Politics", "    - Messages to " + Sys_Empire_Get_Empire_Name(plr_index) + ":")
            call Send_Message_To_Entity(plr_index, 0)
          else
           // Debug output
           call Sys_Debug_Print("Politics", "    - None")
          endif
        endif
      endif
    endfor
  endif

  // Send messages to other alliances
  set alliance_count := Sys_Get_Number_Of_Alliances()

  if (alliance_count > 0) then
    for alliance_index := 1 to alliance_count do
      // Reset special text
      if (alliance_index <> our_alliance) and (lst_Message_Sent_To_Alliance.Get(alliance_index) = 0) and (Sys_Empire_Politics_Is_Alliance_Known(sys_long_Player_ID, alliance_index)) then
        call Send_Message_To_Entity(0, alliance_index)
      endif
    endfor
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Send_Message_To_Entity
//------------------------------------------------------------------------
function Send_Message_To_Entity returns boolean
params
  to_plr:                    long
  to_alliance:               long
vars
  new_msg_type:              long
  new_log_id:                long := 0
  anger_towards_plr:         long
  fear_towards_plr:          long
  fear_mod:                  long
  target_priority:           long
  target_priority_mod:       long
  coop_level:                long
  pol_status:                long
  pol_status_time:           long
  entity_name:               string
  treaty_name:               string
  other_plr:                 long
  other_alliance:            long
  target_system_id:          long
  target_sobj_id:            long
  msg_text:                  string
  treaty_to_propose:         string
  plr_on_our_team:           boolean := FALSE
begin

  // Note our relations with the selected player or alliance
  if (to_plr > 0) then
    set pol_status := Sys_Empire_Politics_Get_Status_With_Player(sys_long_Player_ID, to_plr)
    set pol_status_time := Sys_Empire_Politics_Get_Status_Time_With_Player(sys_long_Player_ID, to_plr)
    set anger_towards_plr := lst_Politics_Anger_Towards_Player.get(to_plr)
    set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(to_plr)
    set target_priority := lst_Politics_Target_Player_Priority.get(to_plr) ^ 2
    set coop_level := lst_Politics_Cooperation_Level.get(to_plr)
    set plr_on_our_team := Sys_Empire_Politics_Is_Player_On_Our_Team(sys_long_Player_ID, to_plr)
    set entity_name := Sys_Empire_Get_Empire_Name(to_plr)
  else
    set pol_status := Sys_Empire_Politics_Get_Status_With_Alliance(sys_long_Player_ID, to_alliance)
    set pol_status_time := Sys_Empire_Politics_Get_Status_Time_With_Alliance(sys_long_Player_ID, to_alliance)
    set anger_towards_plr := lst_Politics_Anger_Towards_Alliance.get(to_alliance)
    set fear_towards_plr := lst_Politics_Fear_Towards_Alliance.get(to_alliance)
    set target_priority := lst_Politics_Target_Alliance_Priority.get(to_alliance)
    set entity_name := Sys_Alliance_Get_Alliance_Name(to_alliance)
  endif

  // Prepare to send a message
  set new_log_id := Sys_Empire_Politics_Create_Temporary_Message(sys_long_Player_ID)

  if (to_plr > 0) then
    call Sys_Empire_Politics_Set_Message_To_Empire(new_log_id, to_plr)
  else
    call Sys_Empire_Politics_Set_Message_To_Alliance(new_log_id, to_alliance)
  endif

  // Set our fear modifier
  if (fear_towards_plr >= 0) then
    set fear_mod := fear_mod + Sys_Trunc(fear_towards_plr ^ 0.5)
  else
    set fear_mod := fear_mod - Sys_Trunc((-fear_towards_plr) ^ 0.5)
  endif

  // Set our target priority modifier
  if (lng_AI_Num_Of_Wars > 2) or (lng_AI_Num_Of_Enemies > 4) then
    set target_priority_mod := TARGET_PRIORITY_HIGH
  else
    set target_priority_mod := TARGET_PRIORITY_MEDIUM
  endif

  // Set our message's tone
  call Sys_Empire_Politics_Set_Message_Tone(new_log_id, Get_Message_Tone(to_plr, to_alliance))

  // Message - Declare War
  if (new_msg_type = 0) then
    set new_msg_type := POLITICS_MSG_DECLARE_WAR

    // Don't declare war if we are not angry enough
    if (new_msg_type > 0) and (anger_towards_plr < lng_Politics_Min_Anger_To_Declare_War + fear_mod) then
      set new_msg_type := 0
    endif

    // Set a chance that we won't declare war based on our priority level versus that player
    if (target_priority < target_priority_mod) then
      set new_msg_type := 0
    endif

    // Don't declare war if we've recently signed a treaty
    if (pol_status_time < lng_Politics_Min_Time_To_Declare_War) then
      set new_msg_type := 0
    endif

    // Declare war if we accepted a request from another player
    if Is_Specific_Request(POLITICS_MSG_REQUEST_DECLARE_WAR_ON_EMPIRE, to_plr, to_alliance) then
      set new_msg_type := POLITICS_MSG_DECLARE_WAR
    endif

    // Don't declare war against AI players if we are using AI team mode!
    if Sys_Is_Game_Using_Teams() and (plr_on_our_team) then
      set new_msg_type := 0
    endif

    // Don't declare war if we are already at war with the selected player
    if (new_msg_type > 0) and (pol_status = POLITICAL_STATUS_TYPE_WAR) then
      set new_msg_type := 0
    endif
  endif

  // Message - Break Treaty
  if (new_msg_type = 0) then
    set new_msg_type := POLITICS_MSG_BREAK_TREATY

    // Don't break treaty if we are not angry enough
    if (new_msg_type > 0) and (anger_towards_plr < lng_Politics_Min_Anger_To_Break_Treaty + fear_mod) then
      set new_msg_type := 0
    endif

    // Don't break our treaty with a low priority player
    if (target_priority < target_priority_mod) then
      set new_msg_type := 0
    endif

    // Don't break our treaty if it is relatively new
    if (pol_status = POLITICAL_STATUS_TYPE_TREATY) and (pol_status_time < lng_Politics_Min_Time_To_Break_Treaty) then
      set new_msg_type := 0
    endif

    // Don't break treaties with AI players if we are using AI team mode!
    if Sys_Is_Game_Using_Teams() and (plr_on_our_team) then
      set new_msg_type := 0
    endif

    // Don't break our treaty if we don't have one to start with
    if (new_msg_type > 0) and (pol_status <> POLITICAL_STATUS_TYPE_TREATY) then
      set new_msg_type := 0
    endif

    // If we are going to break the treaty we'll need a reason
    if (new_msg_type > 0) then
      // Special text
      case Sys_Get_Random_Long(1, 3)
        1:
          set str_Break_Reason := "Break Treaty Anger 1"
        2:
          set str_Break_Reason := "Break Treaty Anger 2"
        3:
          set str_Break_Reason := "Break Treaty Anger 3"
      endcase

      // Break our treaty if we accepted a request from another player
      if (target_priority ^ 2 > Sys_Get_Random_Long(1, 10)) and Is_Specific_Request(POLITICS_MSG_REQUEST_BREAK_TREATY_WITH_EMPIRE, to_plr, to_alliance) then
        set new_msg_type := POLITICS_MSG_BREAK_TREATY
        set str_Break_Reason := "Break Treaty Peer Pressure"
      endif

      // Break our treaty with the mega evil player!
      if (bool_Mega_Evil_Activated) then
        if Sys_Empire_Politics_Is_Player_The_Ultimate_Evil(sys_long_Player_ID, to_plr) then
          if (Sys_Get_Random_Long(1, 200) < anger_towards_plr) then
            set new_msg_type := POLITICS_MSG_BREAK_TREATY
            set str_Break_Reason := "Break Treaty Mega Evil"
          endif
        endif
      endif
    endif
  endif

  // Message - Propose Treaty
  if (new_msg_type = 0) then
    set new_msg_type := POLITICS_MSG_PROPOSE_TREATY

    // Don't propose a treaty to the mega evil player!
    if Sys_Is_Game_Using_Ultimate_Evil_Player() and Sys_Empire_Politics_Is_Player_The_Ultimate_Evil(sys_long_Player_ID, to_plr) then
      set new_msg_type := 0
    endif

    // Don't propose a treaty if it exceeds our maximum allowed anger to propose a treaty
    if (new_msg_type > 0) and (anger_towards_plr >= lng_Politics_Max_Anger_To_Propose_Treaty + fear_mod) then
      set new_msg_type := 0
    endif

    // Consider making peace if our empire is struggling
    if (pol_status = POLITICAL_STATUS_TYPE_WAR) then
      if (target_priority < target_priority_mod) or (fear_towards_plr > lng_Politics_Min_Fear_To_Make_Peace) or (bool_AI_Strategy_Seek_Peace) then
        set new_msg_type := POLITICS_MSG_PROPOSE_TREATY
      endif
    endif

    // Consider proposing a treaty with our enemies if requested by another empire
    if (target_priority ^ 2 < Sys_Get_Random_Long(1, 10)) and Is_Specific_Request(POLITICS_MSG_REQUEST_MAKE_PEACE_WITH_EMPIRE, to_plr, to_alliance) then
      set new_msg_type := POLITICS_MSG_PROPOSE_TREATY
    endif

    // Make treaties with AI players if we are in AI team mode!
    if Sys_Is_Game_Using_Teams() and (plr_on_our_team) then
      set new_msg_type := POLITICS_MSG_PROPOSE_TREATY
    endif

    // Don't propose a treaty all the time if we don't have a treaty in place
    if (Sys_Get_Random_Long(1, 100) > lng_Politics_Percent_Chance_To_Propose_Treaty) or (pol_status = POLITICAL_STATUS_TYPE_TREATY) then
      set new_msg_type := 0
    endif

    // Consider a treaty if the selected player is a low priority target
    if (not Sys_Is_Game_Using_Teams()) then
      if (pol_status = POLITICAL_STATUS_TYPE_KNOWN) or (pol_status = POLITICAL_STATUS_TYPE_WAR) then
        if (target_priority < target_priority_mod) and (anger_towards_plr < lng_Politics_Min_Anger_To_Break_Treaty) then
          set new_msg_Type := POLITICS_MSG_PROPOSE_TREATY
        endif
      endif
    endif

    // Every so often consider making changes to our treaty (Really changing, but like proposing a new treaty)
    if (pol_status = POLITICAL_STATUS_TYPE_TREATY) and (Sys_Get_Random_Long(1, 100) <= lng_Politics_Percent_Chance_To_Change_Treaty) then
      set new_msg_type := POLITICS_MSG_PROPOSE_CHANGES_IN_TREATY
    endif

    // Don't request a treaty if we just sent a request recently
    if ((new_msg_type = POLITICS_MSG_PROPOSE_TREATY) or  (new_msg_type = POLITICS_MSG_PROPOSE_CHANGES_IN_TREATY)) and ((lst_Date_Treaty_Last_Offered.get(to_plr) + 5) > sys_long_Game_Date) then
      set new_msg_type := 0
    endif

    // Don't attempt to send a revision too soon
    if (pol_status = POLITICAL_STATUS_TYPE_TREATY) and (pol_status_time < lng_Politics_Min_Time_To_Accept_Treaty_Change) then
      set new_msg_type := 0
    endif

    // Don't ever propose a treaty to human players if we are using AI team mode!
    if Sys_Is_Game_Using_Teams() and (not plr_on_our_team) then
      set new_msg_type := 0
    endif

    // Pick the Treaty type and its elements
    if (new_msg_type = POLITICS_MSG_PROPOSE_TREATY) or (new_msg_type = POLITICS_MSG_PROPOSE_CHANGES_IN_TREATY) then
      set treaty_to_propose := Get_Treaty_To_Propose(to_plr, to_alliance)

      if (treaty_to_propose <> "") then
        if Get_Treaty_Elements_To_Propose(new_log_id, to_plr, to_alliance, new_msg_type, treaty_to_propose) then
          set treaty_name := Get_Treaty_Name(treaty_to_propose)
          // Consider appending the treaty name
          if str_Treaty_Reason = "Add Share Technology" then
            case treaty_to_propose
              "Cooperative Treaty":
                case Sys_Get_Random_Long(1, 3)
                  1:
                    set treaty_name := "Economic & Technology Alliance"
                  2:
                    set treaty_name := "Trade & Research Exchange"
                endcase
              "Trade Treaty":
                case Sys_Get_Random_Long(1, 4)
                  1:
                    set treaty_name := "Trade & Research Agreement"
                  2:
                    set treaty_name := "Trade & Technology Treaty"
                  3:
                    set treaty_name := "Technology & Trade Alliance"
                endcase
            endcase
          endif
          // Add the treaty name to the log message
          call Sys_Empire_Log_Set_Log_Entry_Message_Treaty_Name(new_log_id, treaty_name)
        else
          set new_msg_type := 0
        endif
      else
        set new_msg_type := 0
      endif
    endif
  endif

  // Message - Propose a Trade (New)
  if (new_msg_type = 0) then
    if (anger_towards_plr <= lng_Politics_Max_Anger_To_Trade) and (coop_level >= COOP_LEVEL_MEDIUM) and (Sys_Get_Random_Long(1, 4 + lng_AI_Categorization) = 1) then
      if Get_Trade_To_Propose(to_plr, new_log_id) then
        set new_msg_type := POLITICS_MSG_PROPOSE_TRADE
      endif
    endif
  endif

  // Message - Follow up Economic Assistance request (Test)
  if (new_msg_type = 0) then
    if (lst_AI_Give_Resource_Assistance_to_Empire.indexof(to_plr) > 0) then
      set new_msg_type := POLITICS_MSG_GIVE_GIFT
      // Fulfill only request to provide economic assistance
      call Sys_Empire_Log_Add_Package_Items(new_log_id, PACKAGE_TYPE_GIVE, MESSAGE_PACKAGE_ITEM_TYPE_RESOURCE, RESOURCE_TYPE_MINERALS, 5000)
    endif
  endif

  // Message - Follow up Technological request (Pending)
  // Message - Follow up Intelligence request (Pending)

  // Message - Warning or Request
  if (new_msg_type = 0) then
    if (lst_Date_Last_Request_Made.get(to_plr) + Sys_Get_Random_Long(5, 15) < sys_long_Game_Date) then
      set new_msg_type := Get_Warning_Message_To_Send(new_log_id, to_plr, other_plr, target_system_id, target_sobj_id)
    endif
  endif

  // Send our message
  if (new_msg_type > 0) then
    set msg_text := Get_Message_Text(new_msg_type, 0, to_plr, to_alliance, other_plr, other_alliance, treaty_name, "", target_system_id, target_sobj_id)
    // Pending
    if (msg_text <> "") then
      call Sys_Empire_Politics_Set_Message_Type(new_log_id, new_msg_type)
      call Sys_Empire_Politics_Set_Message_Text(new_log_id, msg_text)
      call Sys_Empire_Politics_Send_Message(new_log_id)
      // Debug output
      call Sys_Debug_Print("Politics", "    - Sent message " + Get_Message_Type(new_msg_type))
      call Sys_Debug_Print("Politics", "      - Message Text = " + msg_text)
    endif
    // Remember the last time we sent a treaty offer to the selected player
    if (to_plr > 0) and ((new_msg_type = POLITICS_MSG_PROPOSE_TREATY) or (new_msg_type = POLITICS_MSG_PROPOSE_CHANGES_IN_TREATY)) then
      call lst_Date_Treaty_Last_Offered.set(to_plr, sys_long_Game_Date)
    endif
  else
    // Debug output
    call Sys_Debug_Print("Politics", "      - None")
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Get_Treaty_To_Propose
//------------------------------------------------------------------------
function Get_Treaty_To_Propose returns string
params
  to_plr:                    long
  to_alliance:               long
vars
  anger_towards_plr:         long
  fear_towards_plr:          long
  target_priority:           long
  target_priority_mod:       long
  coop_level:                long
  pol_status:                long
  our_primary_enemy:         long
  our_primary_weak_enemy:    long
  our_primary_combat_enemy:  long
  their_primary_enemy:       long
  treaty_to_propose:         string := ""
begin

  // Note our main enemies...
  set our_primary_enemy := lng_Politics_Primary_Enemy
  set our_primary_combat_enemy := lng_Politics_Primary_Weak_Enemy
  set our_primary_combat_enemy := lng_Combat_Primary_Enemy

  // Note our political status, anger, fear, target priority and cooperation status towards the selected player
  if (to_plr > 0) then
    set pol_status := Sys_Empire_Politics_Get_Status_With_Player(sys_long_Player_ID, to_plr)
    set anger_towards_plr := lst_Politics_Anger_Towards_Player.get(to_plr)
    set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(to_plr)
    set target_priority := lst_Politics_Target_Player_Priority.get(to_plr)
    set coop_level := lst_Politics_Cooperation_Level.get(to_plr)
    set their_primary_enemy := Sys_Get_AI_Storage_Long(to_plr, 1, 3)
  else
    // ...or alliance (basic only)
    set pol_status := Sys_Empire_Politics_Get_Status_With_Alliance(sys_long_Player_ID, to_alliance)
    set anger_towards_plr := lst_Politics_Anger_Towards_Alliance.get(to_alliance)
    set fear_towards_plr := lst_Politics_Fear_Towards_Alliance.get(to_alliance)
    set target_priority := lst_Politics_Target_Alliance_Priority.get(to_alliance)
  endif

  // Modify our anger value based on fear
  set anger_towards_plr := anger_towards_plr - Sys_Divide_Long(fear_towards_plr, 2)

  // Set modifier for target priority
  if (lng_AI_Num_Of_Wars > 2) or (lng_AI_Num_Of_Enemies > 4) then
    set target_priority_mod := TARGET_PRIORITY_MEDIUM
  else
    set target_priority_mod := TARGET_PRIORITY_HIGH
  endif

  // Choose the type of Treaty based on our anger/fear and cooperation level towards the selected player
  // Choose Ceasefire if we are at war with a player who is much stronger than us
  if (pol_status = POLITICAL_STATUS_TYPE_WAR) then
    if (target_priority < target_priority_mod) or (fear_towards_plr > (lng_Politics_Min_Fear_To_Make_Peace - (lng_AI_Num_Of_Wars * 5))) then
      set treaty_to_propose := "Ceasefire"
    endif
    // ...or if our empire is continuously struggling
    if (lng_AI_Empire_Progress <= AI_EMPIRE_PROGRESS_POOR) and (lng_AI_Empire_Progress_Time >= 20) then
      set treaty_to_propose := "Ceasefire"
    endif
  endif

  // Choose Partnership Treaty if our cooperation level is high
  if treaty_to_propose = "" and (coop_level >= COOP_LEVEL_PARTNER) then
    set treaty_to_propose := "Partnership Treaty"
  endif

  // Choose Military Alliance if our cooperation status is medium or high
  if treaty_to_propose = "" and (coop_level >= COOP_LEVEL_HIGH) then
    // ...but only if their primary enemy is one of our enemies
    if (their_primary_enemy = our_primary_enemy) or (their_primary_enemy = our_primary_weak_enemy) or (their_primary_enemy = our_primary_combat_enemy) then
      set treaty_to_propose := "Military Alliance"
    endif
  endif

  // Choose a Cooperative Treaty if our cooperation status is medium and the player is not a high risk
  if treaty_to_propose = "" and (coop_level >= COOP_LEVEL_MEDIUM) and (target_priority <= TARGET_PRIORITY_LOW) then
    set treaty_to_propose := "Cooperative Treaty"
  endif

  // Choose a general Trade Treaty if our relations are just ok or going ok but the player is a moderate risk
  if treaty_to_propose = "" and (coop_level >= COOP_LEVEL_LOW) and (target_priority <= TARGET_PRIORITY_MEDIUM) then
    set treaty_to_propose := "Trade Treaty"
  endif

  // Choose a Non-Aggression or Non-Interference treaty if our relations are not so good
  if treaty_to_propose = "" and (coop_level <= COOP_LEVEL_LOW) and (anger_towards_plr < lng_Politics_Max_Anger_To_Accept_Treaty) then
    case Sys_Get_Random_Long(1, 2)
      1:
        set treaty_to_propose := "Non-Aggression Treaty"
      2:
        set treaty_to_propose := "Non-Intercourse Treaty"
    endcase
  endif

  // If we are much stronger, propose a Protectorate or Subjugation Treaty
  if (fear_towards_plr < -30) and (fear_towards_plr >= -50) then
    set treaty_to_propose := "Protectorate Treaty"
  endif
  if (fear_towards_plr < -50) then
    set treaty_to_propose := "Subjugation Treaty"
  endif

  return treaty_to_propose
end

//------------------------------------------------------------------------
// Get_Treaty_Name
//------------------------------------------------------------------------
function Get_Treaty_Name returns string
params
  treaty_to_propose:         string
vars
  treaty_name:               string := ""
begin

  // Choose a suitable name for our proposed treaty
  case treaty_to_propose
    "Partnership Treaty":
      case Sys_Get_Random_Long(1, 4)
        1:
          set treaty_name := "Alliance"
        2:
          set treaty_name := "Partnership Treaty"
        3:
          set treaty_name := "Treaty of Cooperation"
        4:
          set treaty_name := "Treaty of Friendship"
      endcase
    "Military Alliance":
      case Sys_Get_Random_Long(1, 3)
        1:
          set treaty_name := "Military Alliance"
        2:
          set treaty_name := "Mutual Defense Pact"
        3:
          set treaty_name := "Mutual Protection Agreement"
       endcase
    "Cooperative Treaty":
      case Sys_Get_Random_Long(1, 4)
        1:
          set treaty_name := "Cooperation Agreement"
        2:
          set treaty_name := "Mutual Aid Agreement"
        3:
          set treaty_name := "Mutual Assistance Agreement"
        4:
          set treaty_name := "Treaty of Cooperation"
      endcase
    "Trade Treaty":
      case Sys_Get_Random_Long(1, 6)
        1:
          set treaty_name := "Trade Agreement"
        2:
          set treaty_name := "Trade Alliance"
        3:
          set treaty_name := "Trade Pact"
        4:
          set treaty_name := "Trade Treaty"
        5:
          set treaty_name := "Mutual Aid Agreement"
        6:
          set treaty_name := "Resource Alliance"
      endcase
    "Non-Aggression Treaty":
      case Sys_Get_Random_Long(1, 2)
        1:
          set treaty_name := "Non-Aggression Pact"
        2:
          set treaty_name := "Non-Aggression Treaty"
      endcase
    "Non-Intercourse Treaty":
      case Sys_Get_Random_Long(1, 3)
        1:
          set treaty_name := "Non-Intercourse Agreement"
        2:
          set treaty_name := "Non-Interference Treaty"
        3:
          set treaty_name := "Neutrality Pact"
      endcase
    "Ceasefire":
      case Sys_Get_Random_Long(1, 3)
        1:
          set treaty_name := "Ceasefire Agreement"
        2:
          set treaty_name := "Cessation of Hostilities"
        3:
          set treaty_name := "Peace Accords"
      endcase
    "Protectorate Treaty":
      case Sys_Get_Random_Long(1, 2)
        1:
          set treaty_name := "Protectorate Treaty"
        2:
          set treaty_name := "Protectorate Agreement"
      endcase
    "Subjugation Treaty":
      case Sys_Get_Random_Long(1, 2)
        1:
          set treaty_name := "Subjugation Treaty"
        2:
          set treaty_name := "Tribute Agreement"
      endcase
  endcase

  return treaty_name
end

//------------------------------------------------------------------------
// Get_Treaty_Elements_To_Propose
//------------------------------------------------------------------------
function Get_Treaty_Elements_To_Propose returns boolean
params
  new_log_id:                long
  to_plr:                    long
  to_alliance:               long
  new_msg_type:              long
  treaty_to_propose:         string
vars
  lst_proposed_elem_type:    longlist
  lst_proposed_elem_chance:  longlist
  lst_elem_type:             longlist
  lst_elem_value:            longlist
  lst_cur_elem_type:         longlist
  lst_cur_elem_value:        longlist
  list_count:                long
  list_index:                long
  entity_type_A:             long
  entity_id_A:               long
  entity_type_B:             long
  entity_id_B:               long
  to_plr_name:               string
  treaty_elem_type_id:       long
  treaty_elem_type_chance:   long
  treaty_elem_value:         long
  treaty_selected:           boolean := FALSE
begin

  // Identify the parties involved
  if (to_plr > 0) then
    set entity_type_A := ENTITY_TYPE_EMPIRE
    set entity_id_A := sys_long_Player_ID
    set entity_type_B := ENTITY_TYPE_EMPIRE
    set entity_id_B := to_plr
    set to_plr_name := Sys_Empire_Get_Empire_Name(to_plr)
  else
    set entity_type_A := ENTITY_TYPE_EMPIRE
    set entity_id_A := sys_long_Player_ID
    set entity_type_B := ENTITY_TYPE_ALLIANCE
    set entity_id_B := to_alliance
    set to_plr_name := Sys_Alliance_Get_Alliance_Name(to_plr)
  endif

  // Pick the appropriate terms for the proposed treaty package
  case treaty_to_propose
    "Partnership Treaty":
    set treaty_selected := TRUE
    // Possible elements elements
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_TRADE_PERCENT)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_MUTUAL_DEFENSE_PACT)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_ALLOW_MIGRATION_BETWEEN_COLONIES)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_NON_AGGRESSION)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_RESUPPLY)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_REPAIR)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_TECHNOLOGY)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_SYSTEM_MAPS)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_COMMUNICATION_CHANNELS)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_SENSOR_INFO)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_DESIGNS)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_CODES_FOR_MINEFIELDS)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_PLAGUE_CURING)
    call lst_proposed_elem_chance.add(100)
  "Military Alliance":
    set treaty_selected := TRUE
    // Possible elements treaty elements
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_TRADE_PERCENT)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_MUTUAL_DEFENSE_PACT)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_ALLOW_MIGRATION_BETWEEN_COLONIES)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_NON_AGGRESSION)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_RESUPPLY)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_REPAIR)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_TECHNOLOGY)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_SYSTEM_MAPS)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_COMMUNICATION_CHANNELS)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_SENSOR_INFO)
    call lst_proposed_elem_chance.add(75)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_DESIGNS)
    call lst_proposed_elem_chance.add(75)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_CODES_FOR_MINEFIELDS)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_PLAGUE_CURING)
    call lst_proposed_elem_chance.add(50)
  "Cooperative Treaty":
    set treaty_selected := TRUE
    // Possible treaty elements
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_TRADE_PERCENT)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_NON_AGGRESSION)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_RESUPPLY)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_REPAIR)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_TECHNOLOGY)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_SYSTEM_MAPS)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_COMMUNICATION_CHANNELS)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_SENSOR_INFO)
    call lst_proposed_elem_chance.add(75)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_DESIGNS)
    call lst_proposed_elem_chance.add(75)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_CODES_FOR_MINEFIELDS)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_PLAGUE_CURING)
    call lst_proposed_elem_chance.add(50)
  "Trade Treaty":
    set treaty_selected := TRUE
    // Possible treaty elements
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_TRADE_PERCENT)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_NON_AGGRESSION)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_RESUPPLY)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_REPAIR)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_SYSTEM_MAPS)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_COMMUNICATION_CHANNELS)
    call lst_proposed_elem_chance.add(25)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_CODES_FOR_MINEFIELDS)
    call lst_proposed_elem_chance.add(25)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_PLAGUE_CURING)
    call lst_proposed_elem_chance.add(25)
  "Non-Aggression Treaty":
    set treaty_selected := TRUE
    // Possible treaty elements
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_NON_AGGRESSION)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_CODES_FOR_MINEFIELDS)
    call lst_proposed_elem_chance.add(25)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_RESOURCE_TARIFF)
    call lst_proposed_elem_chance.add(100)
  "Non-Intercourse Treaty":
    set treaty_selected := TRUE
    // Possible treaty elements
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_NON_AGGRESSION)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_RESOURCE_TARIFF)
    call lst_proposed_elem_chance.add(100)
  "Ceasefire":
    set treaty_selected := TRUE
    // Possible treaty elements
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_NON_AGGRESSION)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_RESOURCE_TARIFF)
    call lst_proposed_elem_chance.add(100)
  "Protectorate Treaty":
    set treaty_selected := TRUE
    // Possible treaty elements
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_RESOURCE_TARIFF)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_ALLOW_MIGRATION_BETWEEN_COLONIES)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_NON_AGGRESSION)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_RESUPPLY)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_REPAIR)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_TECHNOLOGY)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_SYSTEM_MAPS)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_COMMUNICATION_CHANNELS)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_SENSOR_INFO)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_DESIGNS)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_CODES_FOR_MINEFIELDS)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_PLAGUE_CURING)
    call lst_proposed_elem_chance.add(50)
  "Subjugation Treaty":
    set treaty_selected := TRUE
    // Possible treaty elements
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_RESOURCE_TARIFF)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_ALLOW_MIGRATION_BETWEEN_COLONIES)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_NON_AGGRESSION)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_RESUPPLY)
    call lst_proposed_elem_chance.add(25)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_REPAIR)
    call lst_proposed_elem_chance.add(25)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_TECHNOLOGY)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_SYSTEM_MAPS)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_COMMUNICATION_CHANNELS)
    call lst_proposed_elem_chance.add(25)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_SENSOR_INFO)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_DESIGNS)
    call lst_proposed_elem_chance.add(50)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_CODES_FOR_MINEFIELDS)
    call lst_proposed_elem_chance.add(100)
    call lst_proposed_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_PLAGUE_CURING)
    call lst_proposed_elem_chance.add(50)
  endcase

  // Run through the provisional list to see if the proposed elements are appropriate or useful to us
  set list_count := lst_proposed_elem_type.count()

  if (list_count > 0) then
    // Debug Output
    call Sys_Debug_Print("Politics", "    - Proposed Treaty Type = " + treaty_to_propose)
    call Sys_Debug_Print("Politics", "      - Treaty Elements Proposed:")
    // Pending
    for list_index := 1 to list_count do
      set treaty_elem_type_id := lst_proposed_elem_type.get(list_index)
      set treaty_elem_type_chance := lst_proposed_elem_chance.get(list_index)
      set treaty_elem_value := 0

      // Potentially skip over optional treaty elements
      if Sys_Get_Random_Long(1, 100) > (treaty_elem_type_chance) then
        set treaty_elem_type_id := 0
      endif

      case treaty_elem_type_id
        TREATY_ELEMENT_TYPE_TRADE_PERCENT:
          if (bool_ModAITreatySetting_Allow_Trade) and (bool_ModAITreatySetting_Offer_Trade) then
            // Choose an appropriate treaty element value
            set treaty_elem_value := Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_TRADE_PERCENT, TRUE)
            // Add element to the treaty proposal
            if (treaty_elem_value > 0) then
              call lst_elem_type.add(TREATY_ELEMENT_TYPE_TRADE_PERCENT)
              call lst_elem_value.add(treaty_elem_value)
              // Debug Output
              call Sys_Debug_Print("Politics", "        - " + Get_Treaty_Element_Type_Details(treaty_elem_type_id, treaty_elem_value, entity_id_A, entity_id_B))
            endif
          endif
        TREATY_ELEMENT_TYPE_NON_AGGRESSION:
          // Choose an appropriate treaty element value
          set treaty_elem_value := Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_NON_AGGRESSION, TRUE)
          // Add element to the treaty proposal
          if (treaty_elem_value > 0) then
            call lst_elem_type.add(TREATY_ELEMENT_TYPE_NON_AGGRESSION)
            call lst_elem_value.add(treaty_elem_value)
            // Debug Output
            call Sys_Debug_Print("Politics", "        - " + Get_Treaty_Element_Type_Details(treaty_elem_type_id, treaty_elem_value, entity_id_A, entity_id_B))
          endif
        TREATY_ELEMENT_TYPE_MUTUAL_DEFENSE_PACT:
          // Choose an appropriate treaty element value
          set treaty_elem_value := Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_NON_AGGRESSION, TRUE)
          // Add element to the treaty proposal
          if (treaty_elem_value > 0) then
            call lst_elem_type.add(TREATY_ELEMENT_TYPE_MUTUAL_DEFENSE_PACT)
            call lst_elem_value.add(1)
            // Debug Output
            call Sys_Debug_Print("Politics", "        - " + Get_Treaty_Element_Type_Details(treaty_elem_type_id, treaty_elem_value, entity_id_A, entity_id_B))
            // Consider adding a special note
            if (Sys_Get_Random_Long(1, 5) = 1) and (str_Treaty_Reason = "") then
              set str_Treaty_Reason := "Add Mutual Defense"
            endif
          endif
        TREATY_ELEMENT_TYPE_ALLOW_MIGRATION_BETWEEN_COLONIES:
          // Choose an appropriate treaty element value
          if (bool_ModAITreatySetting_Allow_Migration) and (bool_ModAITreatySetting_Offer_Migration) then
            set treaty_elem_value := Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_ALLOW_MIGRATION_BETWEEN_COLONIES, TRUE)
            // Add element to the treaty proposal
            if (treaty_elem_value > 0) then
              call lst_elem_type.add(TREATY_ELEMENT_TYPE_ALLOW_MIGRATION_BETWEEN_COLONIES)
              call lst_elem_value.add(treaty_elem_value)
              // Debug Output
              call Sys_Debug_Print("Politics", "        - " + Get_Treaty_Element_Type_Details(treaty_elem_type_id, treaty_elem_value, entity_id_A, entity_id_B))
            endif
          endif
        TREATY_ELEMENT_TYPE_TREATIES_WITH_OTHERS:
          // Skip
        TREATY_ELEMENT_TYPE_SHARE_RESUPPLY:
          // Choose an appropriate treaty element value
          set treaty_elem_value := Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_SHARE_RESUPPLY, TRUE)
          // Add element to the treaty proposal
          if (treaty_elem_value > 0) then
            call lst_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_RESUPPLY)
            call lst_elem_value.add(treaty_elem_value)
            // Debug Output
            call Sys_Debug_Print("Politics", "        - " + Get_Treaty_Element_Type_Details(treaty_elem_type_id, treaty_elem_value, entity_id_A, entity_id_B))
          endif
        TREATY_ELEMENT_TYPE_SHARE_REPAIR:
          // Choose an appropriate treaty element value
          set treaty_elem_value := Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_SHARE_REPAIR, TRUE)
          // Add element to the treaty proposal
          if (treaty_elem_value > 0) then
            call lst_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_REPAIR)
            call lst_elem_value.add(treaty_elem_value)
          endif
        TREATY_ELEMENT_TYPE_SHARE_TECHNOLOGY:
          if (bool_ModAITreatySetting_Allow_Share_Technology) and (bool_ModAITreatySetting_Offer_Share_Technology) then
            // Choose an appropriate treaty element value
            set treaty_elem_value := Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_SHARE_TECHNOLOGY, TRUE)
            // Add element to the treaty proposal
            if (treaty_elem_value > 0) then
              call lst_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_TECHNOLOGY)
              call lst_elem_value.add(Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_SHARE_TECHNOLOGY, TRUE))
              // Debug Output
              call Sys_Debug_Print("Politics", "        - " + Get_Treaty_Element_Type_Details(treaty_elem_type_id, treaty_elem_value, entity_id_A, entity_id_B))
            endif
          endif
        TREATY_ELEMENT_TYPE_SHARE_SYSTEM_MAPS:
          // Are we allowed to share maps?
          if (bool_ModAITreatySetting_Allow_Share_Maps) and (bool_ModAITreatySetting_Offer_Share_Maps) then
            // Choose an appropriate treaty element value
            set treaty_elem_value := Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_SHARE_SYSTEM_MAPS, TRUE)
            // Add element to the treaty proposal
            if (treaty_elem_value > 0) then
              call lst_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_SYSTEM_MAPS)
              call lst_elem_value.add(treaty_elem_value)
              // Debug Output
              call Sys_Debug_Print("Politics", "        - " + Get_Treaty_Element_Type_Details(treaty_elem_type_id, treaty_elem_value, entity_id_A, entity_id_B))
            endif
          endif
        TREATY_ELEMENT_TYPE_SHARE_COMMUNICATION_CHANNELS:
          // Are we allowed to share comm channels?
          if (bool_ModAITreatySetting_Allow_Share_Comm_Channels) and (bool_ModAITreatySetting_Offer_Share_Comm_Channels) then
            // Choose an appropriate treaty element value
            set treaty_elem_value := Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_SHARE_COMMUNICATION_CHANNELS, TRUE)
            // Add element to the treaty proposal
            if (treaty_elem_value > 0) then
              call lst_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_COMMUNICATION_CHANNELS)
              call lst_elem_value.add(treaty_elem_value)
              // Debug Output
              call Sys_Debug_Print("Politics", "        - " + Get_Treaty_Element_Type_Details(treaty_elem_type_id, treaty_elem_value, entity_id_A, entity_id_B))
            endif
          endif
        TREATY_ELEMENT_TYPE_SHARE_ESPIONAGE_INFO:
          // Are we allowed to share espionage info?
          if (bool_ModAITreatySetting_Allow_Share_Espionage_Info) and (bool_ModAITreatySetting_Offer_Share_Espionage_Info) then
            // Choose an appropriate treaty element value
            set treaty_elem_value := Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_SHARE_ESPIONAGE_INFO, TRUE)
            // Add element to the treaty proposal
            if (treaty_elem_value > 0) then
              call lst_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_ESPIONAGE_INFO)
              call lst_elem_value.add(treaty_elem_value)
              // Debug Output
              call Sys_Debug_Print("Politics", "        - " + Get_Treaty_Element_Type_Details(treaty_elem_type_id, treaty_elem_value, entity_id_A, entity_id_B))
            endif
          endif
        TREATY_ELEMENT_TYPE_SHARE_SENSOR_INFO:
          // Are we allowed to share sensor info?
          if (bool_ModAITreatySetting_Allow_Share_Sensor_Info) and (bool_ModAITreatySetting_Offer_Share_Sensor_Info) then
            // Choose an appropriate treaty element value
            set treaty_elem_value := Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_SHARE_SENSOR_INFO, TRUE)
            // Add element to the treaty proposal
            if (treaty_elem_value > 0) then
              call lst_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_SENSOR_INFO)
              call lst_elem_value.add(treaty_elem_value)
              // Debug Output
              call Sys_Debug_Print("Politics", "        - " + Get_Treaty_Element_Type_Details(treaty_elem_type_id, treaty_elem_value, entity_id_A, entity_id_B))
            endif
          endif
        TREATY_ELEMENT_TYPE_SHARE_DESIGNS:
          // Are we allowed to share designs?
          if (bool_ModAITreatySetting_Allow_Share_Vehicle_Designs) and (bool_ModAITreatySetting_Offer_Share_Vehicle_Designs) then
            // Choose an appropriate treaty element value
            set treaty_elem_value := Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_SHARE_DESIGNS, TRUE)
            // Add element to the treaty proposal
            if (treaty_elem_value > 0) then
              call lst_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_DESIGNS)
              call lst_elem_value.add(treaty_elem_value)
              // Debug Output
              call Sys_Debug_Print("Politics", "        - " + Get_Treaty_Element_Type_Details(treaty_elem_type_id, treaty_elem_value, entity_id_A, entity_id_B))
            endif
          endif
        TREATY_ELEMENT_TYPE_SHARE_CODES_FOR_MINEFIELDS:
          // Choose an appropriate treaty element value
          set treaty_elem_value := Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_SHARE_CODES_FOR_MINEFIELDS, TRUE)
          // Add element to the treaty proposal
          if (treaty_elem_value > 0) then
            call lst_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_CODES_FOR_MINEFIELDS)
            call lst_elem_value.add(treaty_elem_value)
            // Debug Output
            call Sys_Debug_Print("Politics", "        - " + Get_Treaty_Element_Type_Details(treaty_elem_type_id, treaty_elem_value, entity_id_A, entity_id_B))
          endif
        TREATY_ELEMENT_TYPE_SHARE_COMBAT_REPORTS:
          // Are we allowed to share combat reports?
          if (bool_ModAITreatySetting_Allow_Share_Combat_Reports) and (bool_ModAITreatySetting_Offer_Share_Combat_Reports) then
            // Choose an appropriate treaty element value
            set treaty_elem_value := Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_SHARE_COMBAT_REPORTS, TRUE)
            // Add element to the treaty proposal
            if (treaty_elem_value > 0) then
              call lst_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_COMBAT_REPORTS)
              call lst_elem_value.add(treaty_elem_value)
              // Debug Output
              call Sys_Debug_Print("Politics", "        - " + Get_Treaty_Element_Type_Details(treaty_elem_type_id, treaty_elem_value, entity_id_A, entity_id_B))
            endif
          endif
        TREATY_ELEMENT_TYPE_CANNOT_RESEARCH:
          // Skip
        TREATY_ELEMENT_TYPE_CANNOT_INTELLIGENCE:
          // Skip
        TREATY_ELEMENT_TYPE_CANNOT_BOMBARD_PLANETS:
          // Skip
        TREATY_ELEMENT_TYPE_CANNOT_USE_VIRAL_WEAPONS:
          // Skip
        TREATY_ELEMENT_TYPE_CANNOT_DESTROY_PLANETS:
          // Skip
        TREATY_ELEMENT_TYPE_CANNOT_DESTROY_STARS:
          // Skip
        TREATY_ELEMENT_TYPE_CANNOT_CREATE_BLACKHOLES:
          // Skip
        TREATY_ELEMENT_TYPE_CANNOT_CREATE_NEBULAE:
          // Skip
        TREATY_ELEMENT_TYPE_CANNOT_USE_CLOAKING:
          // Skip
        TREATY_ELEMENT_TYPE_RESOURCE_TARIFF:
          // Choose an appropriate treaty element value
          set treaty_elem_value := Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_RESOURCE_TARIFF, TRUE)
          // Add element to the treaty proposal
          if (treaty_elem_value > 0) then
            call lst_elem_type.add(TREATY_ELEMENT_TYPE_RESOURCE_TARIFF)
            call lst_elem_value.add(treaty_elem_value)
            // Debug Output
            call Sys_Debug_Print("Politics", "        - " + Get_Treaty_Element_Type_Details(treaty_elem_type_id, treaty_elem_value, entity_id_A, entity_id_B))
          endif
        TREATY_ELEMENT_TYPE_SHARE_PLAGUE_CURING:
          // Choose an appropriate treaty element value
          set treaty_elem_value := Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_SHARE_PLAGUE_CURING, TRUE)
          // Add element to the treaty proposal
          if (treaty_elem_value > 0) then
            call lst_elem_type.add(TREATY_ELEMENT_TYPE_SHARE_PLAGUE_CURING)
            call lst_elem_value.add(Get_Specific_Treaty_Element(to_plr, to_alliance, TREATY_ELEMENT_TYPE_SHARE_PLAGUE_CURING, TRUE))
            // Debug Output
            call Sys_Debug_Print("Politics", "        - " + Get_Treaty_Element_Type_Details(treaty_elem_type_id, treaty_elem_value, entity_id_A, entity_id_B))
          endif
      endcase
    endfor
  endif

  // If a treaty has no elements, don't send a message
  if (lst_elem_type.count() <= 0) then
    set treaty_selected := FALSE
  endif

  // Don't propose changes to our treaty if they are not good
  if (new_msg_type = POLITICS_MSG_PROPOSE_CHANGES_IN_TREATY) and (to_alliance = 0) then
    call Sys_Get_Treaty_Elements_Between_Empires(entity_id_A, entity_id_B, lst_cur_elem_type, lst_cur_elem_value)
    // If our proposed treaty has fewer elements, it's probably not worth it to propose
    if (lst_cur_elem_type.count() >= lst_elem_type.count()) then
      set treaty_selected := FALSE
      // Debug output
      call Sys_Debug_Print("Politics", "      - Considered a treaty revision for the " + to_plr_name + " but it wasn't worth it")
    endif
  endif

  // Add our chosen elements to the treaty proposal
  if (treaty_selected) then
    call Sys_Empire_Log_Set_Log_Entry_Message_Treaty_Participants(sys_long_Player_ID, new_log_id, entity_type_A, entity_id_A, entity_type_B, entity_id_B)
    call Sys_Empire_Log_Set_Log_Entry_Message_Treaty_Elements(new_log_id, lst_elem_type, lst_elem_value)
  endif

  return treaty_selected
end

//------------------------------------------------------------------------
// Get_Specific_Treaty_Element
//------------------------------------------------------------------------
function Get_Specific_Treaty_Element returns long
params
  to_plr:                         long
  to_alliance:                    long
  elem_type:                      long
  is_entity_A:                    boolean
vars
  anger_towards_plr:              long
  fear_towards_plr:               long
  coop_level:                     long
  fear_modifier:                  long := 0
  elem_index:                     long
  elem_value:                     long := 0
  elem_concession:                long
  elem_coop_level:                long
  start_pos:                      long
  human_plr:                      boolean := FALSE
begin

  // Get our anger, fear and cooperation level for the other player
  if (to_plr > 0) then
    set anger_towards_plr := lst_Politics_Anger_Towards_Player.get(to_plr) - fear_towards_plr
    set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(to_plr)
    set coop_level := lst_Politics_Cooperation_Level.get(to_plr)
    set human_plr := not Sys_Are_We_Computer_Player(to_plr)
  else
    set anger_towards_plr := lst_Politics_Anger_Towards_Alliance.get(to_alliance) - fear_towards_plr
    set fear_towards_plr := lst_Politics_Fear_Towards_Alliance.get(to_alliance)
  endif

  // If we are entity B, then flip our fear value to select the correct treaty elements when countering an existing treaty
  if (is_entity_A) then
    // Do nothing
  else
    set fear_towards_plr := -fear_towards_plr
  endif

  // Set the start position
  set start_pos := lng_Politics_Treaty_Elements_Allowed_Type.indexof(elem_type) - 1

  // Choose a specific treaty element based on anger, fear and our cooperation level
  // Demand concession elements sometimes if we are stronger (negative fear towards player)
  // Propose concession elements sometimes if we are weaker (positive fear towards player)
  // The weaker or stronger our fear, the more elements we'll concede or ask for
  // For mutual items like trade, consider our anger level only
  // Cross-check with our level of cooperation
  case elem_type
    TREATY_ELEMENT_TYPE_TRADE_PERCENT:
      // If trade is allowed, pick an appropriate element value
      if (bool_ModAITreatySetting_Allow_Trade) then
        set elem_value := 1
        // Select the highest trade level based on anger and cooperation levels
        for elem_index := 1 to 6 do
          if (anger_towards_plr <= lng_Politics_Treaty_Elements_Allowed_Max_Anger.get(start_pos + elem_index)) then
            set elem_value := elem_index
          endif
          // Adjust for our cooperation level
          set elem_value := Sys_Min_Long(elem_value, coop_level + 2)
        endfor
        // Increase trade percent offer if we are low on resources
        if (bool_Race_Minerals_Low) or (bool_Race_Organics_Low) or (bool_Race_Radioactives_Low) or (bool_Race_Maintenance_High) or (bool_Enemy_Ahead_In_Resources) then
          set elem_index := Sys_Min_Long(6, elem_value + 2)
        endif
        // Consider adding a special note
        if (Sys_Get_Random_Long(1, 5) = 1) and (str_Treaty_Reason = "") then
          set str_Treaty_Reason := "Add Trade"
        endif
      endif
    TREATY_ELEMENT_TYPE_NON_AGGRESSION:
      // Default is neutral space or all systems depending on cooperation level (Basic Coop = Neutral space; Low Coop = All Systems)
      set elem_value := Sys_Min_Long(2, coop_level)
      // Allow Colonization if our cooperation and anger level allows assuming it's useful to us
      if Is_Treaty_Element_Useful(to_plr, TREATY_ELEMENT_TYPE_NON_AGGRESSION, 3) then
        if (anger_towards_plr <= lng_Politics_Treaty_Elements_Allowed_Max_Anger.get(start_pos + 3)) and (coop_level >= COOP_LEVEL_MEDIUM) then
          set elem_value := 3
        endif
      endif
      // Do not allow colonization to be offered if restricted by mod settings
      if (elem_value = 3 and not bool_ModAITreatySetting_Allow_Colonization) then
        set elem_value := 2
      endif
      // Consider adding a special note
      if (elem_value = 1) and (Sys_Get_Random_Long(1, 4) = 1) and (str_Treaty_Reason = "") then
        set str_Treaty_Reason := "Add Non-Aggression Neutral"
      endif
      if (elem_value = 3) and (Sys_Get_Random_Long(1, 4) = 1) and (str_Treaty_Reason = "") then
        set str_Treaty_Reason := "Add Allow Colonization"
      endif
      // Just in case...!
      if (elem_value < 1) and (elem_value > 3) then
        set elem_value := Sys_Min_Long(2, coop_level)
      endif
      // Flag that we were offered a non-aggression element
      if (elem_value >= 1) and (elem_value <= 3) then
        set gbl_treaty_has_non_aggression := TRUE
      endif
    TREATY_ELEMENT_TYPE_MUTUAL_DEFENSE_PACT:
      // Allow mutual defense if our cooperation and anger level allows assuming it's useful to us
      if Is_Treaty_Element_Useful(to_plr, TREATY_ELEMENT_TYPE_MUTUAL_DEFENSE_PACT, 1) then
        if (anger_towards_plr <= lng_Politics_Treaty_Elements_Allowed_Max_Anger.get(start_pos + 1)) and (coop_level >= COOP_LEVEL_HIGH) then
          set elem_value := 1
        endif
      endif
    TREATY_ELEMENT_TYPE_ALLOW_MIGRATION_BETWEEN_COLONIES:
      // If migration is allowed, pick an appropriate element value
      if (bool_ModAITreatySetting_Allow_Migration) then
        if Is_Treaty_Element_Useful(to_plr, TREATY_ELEMENT_TYPE_ALLOW_MIGRATION_BETWEEN_COLONIES, 3) then
          if (anger_towards_plr <= lng_Politics_Treaty_Elements_Allowed_Max_Anger.get(start_pos + 3)) then
            // Both
            set elem_value := 3
          else
            // B to A only
            if (fear_towards_plr >= Sys_Get_Random_Long(25, 35)) then
              set elem_value := 1
            endif
            // A to B only
            if (fear_towards_plr <= Sys_Get_Random_Long(-35, -25)) then
              set elem_value := 2
            endif
          endif
        endif
      endif
      // Consider adding a special note
      if (Sys_Get_Random_Long(1, 5) = 1) and (str_Treaty_Reason = "") then
        set str_Treaty_Reason := "Add Migration"
      endif
    TREATY_ELEMENT_TYPE_TREATIES_WITH_OTHERS:
      set elem_value := 6
    TREATY_ELEMENT_TYPE_SHARE_RESUPPLY:
      // Share resupply if our cooperation level allows it and it is useful
      if Is_Treaty_Element_Useful(to_plr, TREATY_ELEMENT_TYPE_SHARE_RESUPPLY, 3) and (coop_level >= COOP_LEVEL_LOW) then
        // Both
        set elem_value := 3
        // B to A only
        if (fear_towards_plr >= Sys_Get_Random_Long(5, 10)) then
          set elem_value := 1
        endif
        // A to B only
        if (fear_towards_plr <= Sys_Get_Random_Long(-10, -5)) then
          set elem_value := 2
        endif
        // Don't offer free concessions to human players!
        if (human_plr) then
          set elem_value := 3
        endif
      endif
    TREATY_ELEMENT_TYPE_SHARE_REPAIR:
      // Share repair if our cooperation level allows it and it is useful
      if Is_Treaty_Element_Useful(to_plr, TREATY_ELEMENT_TYPE_SHARE_REPAIR, 3) and (coop_level >= COOP_LEVEL_LOW) then
        // Both  
        set elem_value := 3
        // B to A only
        if (fear_towards_plr >= Sys_Get_Random_Long(5, 10)) then
          set elem_value := 1
        endif
        // A to B only
        if (fear_towards_plr <= Sys_Get_Random_Long(-10, -5)) then
          set elem_value := 2
        endif
        // Don't offer free concessions to human players!
        if (human_plr) then
          set elem_value := 3
        endif
      endif
    TREATY_ELEMENT_TYPE_SHARE_PLAGUE_CURING:
      set elem_value := 3
      // B to A only
      if (fear_towards_plr >= Sys_Get_Random_Long(5, 10)) then
        set elem_value := 1
      endif
      // A to B only
      if (fear_towards_plr <= Sys_Get_Random_Long(-10, -5)) then
        set elem_value := 2
      endif
      // Don't offer free concessions to human players!
      if (human_plr) then
        set elem_value := 3
      endif
    TREATY_ELEMENT_TYPE_SHARE_TECHNOLOGY:
      // If sharing technology is allowed, pick an appropriate element value
      if (bool_ModAITreatySetting_Allow_Share_Technology) and (bool_ModAITreatySetting_Offer_Share_Technology) then
        if Is_Treaty_Element_Useful(to_plr, TREATY_ELEMENT_TYPE_SHARE_TECHNOLOGY, 9) and (coop_level >= COOP_LEVEL_MEDIUM) then
          set elem_value := 9
          // B to A
          for elem_index := 1 to 4 do
            if (fear_towards_plr > elem_index * 15) then
              set elem_value := elem_index
            endif
          endfor
          // A to B
          for elem_index := 5 to 8 do
            if (fear_towards_plr < (elem_index * -15) + 60) then
              set elem_value := elem_index
            endif
          endfor
          // Both
          for elem_index := 9 to 12 do
            if (anger_towards_plr <= lng_Politics_Treaty_Elements_Allowed_Max_Anger.Get(start_pos + elem_index)) and (elem_value > 8) then
              set elem_value := elem_index
            endif
          endfor
          // Consider adding a special note
          if (Sys_Get_Random_Long(1, 2) = 1) and (str_Treaty_Reason = "") then
            set str_Treaty_Reason := "Add Share Technology"
          endif
        endif
      endif
    TREATY_ELEMENT_TYPE_SHARE_SYSTEM_MAPS:
      // If sharing maps is allowed, pick an appropriate element value
      if (bool_ModAITreatySetting_Allow_Share_Maps) and (bool_ModAITreatySetting_Offer_Share_Maps) then
        if Is_Treaty_Element_Useful(to_plr, TREATY_ELEMENT_TYPE_SHARE_SYSTEM_MAPS, 3) and (coop_level >= COOP_LEVEL_LOW) then
          // Both
          set elem_value := 3
          // B to A
          if (fear_towards_plr >= Sys_Get_Random_Long(5, 10)) then
            set elem_value := 1
          endif
          // A to B
          if (fear_towards_plr <= Sys_Get_Random_Long(-10, -5)) then
            set elem_value := 2
          endif
          // Don't offer free concessions to human players!
          if (human_plr) then
            set elem_value := 3
          endif
        endif
      endif
    TREATY_ELEMENT_TYPE_SHARE_COMMUNICATION_CHANNELS:
      // If sharing comm channels is allowed, pick an appropriate element value
      if (bool_ModAITreatySetting_Allow_Share_Comm_Channels) and (bool_ModAITreatySetting_Offer_Share_Comm_Channels) then
        if (coop_level >= COOP_LEVEL_LOW) then
          // Both
          set elem_value := 3
          // B to A
          if (fear_towards_plr >= Sys_Get_Random_Long(5, 10)) then
            set elem_value := 1
          endif
          // A to B
          if (fear_towards_plr <= Sys_Get_Random_Long(-10, -5)) then
            set elem_value := 2
          endif
          // Don't offer free concessions to human players!
          if (human_plr) then
            set elem_value := 3
          endif
        endif
      endif
    TREATY_ELEMENT_TYPE_SHARE_ESPIONAGE_INFO:
      // If sharing espionage info is allowed, pick an appropriate element value if its useful
      if (bool_ModAITreatySetting_Allow_Share_Espionage_Info) and (bool_ModAITreatySetting_Offer_Share_Espionage_Info) then
        if Is_Treaty_Element_Useful(to_plr, TREATY_ELEMENT_TYPE_SHARE_ESPIONAGE_INFO, 3) then
          // Both empires
          set elem_value := 3
          // B to A
          if (fear_towards_plr >= Sys_Get_Random_Long(20, 30)) then
            set elem_value := 1
          endif
          // A to B
          if (fear_towards_plr <= Sys_Get_Random_Long(-30, -20)) then
            set elem_value := 2
          endif
          // Don't offer free concessions to human players!
          if (human_plr) then
            set elem_value := 3
          endif
        endif
      endif
    TREATY_ELEMENT_TYPE_SHARE_SENSOR_INFO:
      // If sharing sensor info is allowed, pick an appropriate element value
      if (bool_ModAITreatySetting_Allow_Share_Sensor_Info) and (bool_ModAITreatySetting_Offer_Share_Sensor_Info) then
          if Is_Treaty_Element_Useful(to_plr, TREATY_ELEMENT_TYPE_SHARE_SENSOR_INFO, 5) then
            // Both
            set elem_value := 5
            // B to A
            for elem_index := 1 to 2 do
              if (fear_towards_plr > (elem_index * 15)) then
                set elem_value := elem_index
              endif
            endfor
            // A to B
            for elem_index := 3 to 4 do
              if (fear_towards_plr < (elem_index * -15) + 30) then
                set elem_value := elem_index
              endif
            endfor
            // Both
            if (anger_towards_plr <= lng_Politics_Treaty_Elements_Allowed_Max_Anger.get(start_pos + 6)) and (elem_value > 4) then
              set elem_value := elem_index
            endif
            // Don't offer free concessions to human players!
            if (human_plr) then
              set elem_value := 5
            endif
          endif
        endif
      endif
    TREATY_ELEMENT_TYPE_SHARE_DESIGNS:
      // If sharing vehicle designs is allowed, pick an appropriate element value
      if (bool_ModAITreatySetting_Allow_Share_Vehicle_Designs) and (bool_ModAITreatySetting_Offer_Share_Vehicle_Designs) then
        if Is_Treaty_Element_Useful(to_plr, TREATY_ELEMENT_TYPE_SHARE_DESIGNS, 5) then
          // Both empires share enemy designs
          set elem_value := 5
          // B to A
          for elem_index := 1 to 2 do
            if (fear_towards_plr > (elem_index * 20)) then
              set elem_value := elem_index
            endif
          endfor
          // A to B
          for elem_index := 3 to 4 do
            if (fear_towards_plr < (elem_index * -20) + 40) then
              set elem_value := elem_index
            endif
          endfor
          // Both empires share all designs
          if (anger_towards_plr <= lng_Politics_Treaty_Elements_Allowed_Max_Anger.get(start_pos + 6)) and (elem_value > 4) then
            set elem_value := 6
          endif
          // Don't offer free concessions to human players!
          if (human_plr) then
            set elem_value := 5
          endif
        endif
      endif
    TREATY_ELEMENT_TYPE_SHARE_COMBAT_REPORTS:
      // If sharing combat reports is allowed, pick an appropriate element value
      if (bool_ModAITreatySetting_Allow_Share_Combat_Reports) and (bool_ModAITreatySetting_Offer_Share_Combat_Reports) then
        if Is_Treaty_Element_Useful(to_plr, TREATY_ELEMENT_TYPE_SHARE_COMBAT_REPORTS, 3) then
          // Both
          set elem_value := 3
          // B to A
          if (fear_towards_plr >= Sys_Get_Random_Long(20, 30)) then
            set elem_value := 1
          endif
          // A to B
          if (fear_towards_plr <= Sys_Get_Random_Long(-30, -20)) then
            set elem_value := 2
          endif
          // Don't offer free concessions to human players!
          if (human_plr) then
            set elem_value := 3
          endif
        endif
      endif
    TREATY_ELEMENT_TYPE_SHARE_CODES_FOR_MINEFIELDS:
      if (bool_ModAITreatySetting_Allow_Share_Minefield_Codes) and (bool_ModAITreatySetting_Offer_Share_Minefield_Codes) then
        if Is_Treaty_Element_Useful(to_plr, TREATY_ELEMENT_TYPE_SHARE_CODES_FOR_MINEFIELDS, 3) then
          // Both
          set elem_value := 3
          // B to A
          if (fear_towards_plr >= Sys_Get_Random_Long(40, 60)) then
            set elem_value := 1
          endif
          // A to B
          if (fear_towards_plr <= Sys_Get_Random_Long(-60, -40)) then
            set elem_value := 2
          endif
          // Don't offer free concessions to human players!
          if (human_plr) then
            set elem_value := 3
          endif
          // Flag that we were offered minefield codes
          if (elem_value = 3) then
            set gbl_treaty_has_minefield_codes := TRUE
          endif
        endif
      endif
    TREATY_ELEMENT_TYPE_CANNOT_RESEARCH:
      set elem_value := 3
      if (fear_towards_plr >= Sys_Get_Random_Long(50, 100)) then
        set elem_value := 1
      endif
      if (fear_towards_plr <= Sys_Get_Random_Long(-100, -50)) then
        set elem_value := 2
      endif
    TREATY_ELEMENT_TYPE_CANNOT_INTELLIGENCE:
      set elem_value := 3
      if (fear_towards_plr >= Sys_Get_Random_Long(50, 100)) then
        set elem_value := 1
      endif
      if (fear_towards_plr <= Sys_Get_Random_Long(-100, -50)) then
        set elem_value := 2
      endif
    TREATY_ELEMENT_TYPE_CANNOT_BOMBARD_PLANETS:
      set elem_value := 3
      if (fear_towards_plr >= Sys_Get_Random_Long(50, 100)) then
        set elem_value := 1
      endif
      if (fear_towards_plr <= Sys_Get_Random_Long(-100, -50)) then
        set elem_value := 2
      endif
    TREATY_ELEMENT_TYPE_CANNOT_USE_VIRAL_WEAPONS:
      set elem_value := 3
      if (fear_towards_plr >= Sys_Get_Random_Long(20, 30)) then
        set elem_value := 1
      endif
      if (fear_towards_plr <= Sys_Get_Random_Long(-30, -20)) then
        set elem_value := 2
      endif
    TREATY_ELEMENT_TYPE_CANNOT_DESTROY_PLANETS:
      set elem_value := 3
      if (fear_towards_plr >= Sys_Get_Random_Long(10, 20)) then
        set elem_value := 1
      endif
      if (fear_towards_plr <= Sys_Get_Random_Long(-20, -10)) then
        set elem_value := 2
      endif
    TREATY_ELEMENT_TYPE_CANNOT_DESTROY_STARS:
      set elem_value := 3
      if (fear_towards_plr >= Sys_Get_Random_Long(10, 20)) then
        set elem_value := 1
      endif
      if (fear_towards_plr <= Sys_Get_Random_Long(-20, -10)) then
        set elem_value := 2
      endif
    TREATY_ELEMENT_TYPE_CANNOT_CREATE_BLACKHOLES:
      set elem_value := 3
      if (fear_towards_plr >= Sys_Get_Random_Long(10, 20)) then
        set elem_value := 1
      endif
      if (fear_towards_plr <= Sys_Get_Random_Long(-20, 10)) then
        set elem_value := 2
      endif
    TREATY_ELEMENT_TYPE_CANNOT_CREATE_NEBULAE:
      set elem_value := 3
      if (fear_towards_plr >= Sys_Get_Random_Long(10, 20)) then
        set elem_value := 1
      endif
      if (fear_towards_plr <= Sys_Get_Random_Long(-20, -10)) then
        set elem_value := 2
      endif
    TREATY_ELEMENT_TYPE_CANNOT_USE_CLOAKING:
      set elem_value := 3
      if (fear_towards_plr >= Sys_Get_Random_Long(30, 40)) then
        set elem_value := 1
      endif
      if (fear_towards_plr <= Sys_Get_Random_Long(-40, -30)) then
        set elem_value := 2
      endif
    TREATY_ELEMENT_TYPE_RESOURCE_TARIFF:
      if (fear_towards_plr > 0) then
        set elem_value := 1
        // Determine the tribute level based on our fear level versus the other player
        for elem_index := 1 to 8 do
          if (fear_towards_plr > elem_index * 10) then
            set elem_value := elem_index
          endif
        endfor
        // Consider adding a special note
        if (Sys_Get_Random_Long(1, 5) = 1) and (str_Treaty_Reason = "") then
          set str_Treaty_Reason := "Give Tribute"
        endif
      else
        set elem_value := 9
        // Determine the tribute level based on our fear level versus the other player
        for elem_index := 9 to 16 do
          if (fear_towards_plr < (elem_index * -10) + 80) then
            set elem_value := elem_index
          endif
          // Consider adding a special note
          if (Sys_Get_Random_Long(1, 5) = 1) and (str_Treaty_Reason = "") then
            set str_Treaty_Reason := "Get Tribute"
          endif
        endfor
      endif
  endcase

  return elem_value
end

//------------------------------------------------------------------------
// Is_Treaty_Element_Useful
//------------------------------------------------------------------------
function Is_Treaty_Element_Useful returns boolean
params
  target_plr:                     long
  elem_type:                      long
  elem_value:                     long
vars
  fear_towards_plr:               long
  avg_sys_dist:                   long
  pct_shared_sys:                 long
  our_atmosphere_type:            long
  our_colonization_ability:       long
  their_atmosphere_type:          long
  their_colonization_ability:     long
  our_tech_levels:                long
  their_tech_levels:              long
  net_tech_value:                 real
  accept_tech_sharing:            boolean := FALSE
  coop_level:                     long
  human_plr:                      boolean := FALSE
  useful_element:                 boolean := TRUE
begin

  // Get our details
  set our_atmosphere_type := lst_Politics_Player_Native_Atmosphere.get(sys_long_Player_ID)
  set our_colonization_ability := lst_Politics_Player_Colonization_Ability.get(sys_long_Player_ID)
  set our_tech_levels := lst_Politics_Player_Tech_Levels.get(sys_long_Player_ID)

  // Get the other player's details
  set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(target_plr)
  set coop_level := lst_Politics_Cooperation_Level.get(target_plr)
  set avg_sys_dist := lst_Politics_Player_Avg_Sys_Dist.get(target_plr)
  set pct_shared_sys := lst_Politics_Player_Overlap_Pct.get(target_plr)
  set their_atmosphere_type := lst_Politics_Player_Native_Atmosphere.get(target_plr)
  set their_colonization_ability := lst_Politics_Player_Colonization_Ability.get(target_plr)
  set their_tech_levels := lst_Politics_Player_Tech_Levels.get(target_plr)
  set human_plr := (not Sys_Are_We_Computer_Player(target_plr))

  // Research
  set net_tech_value := (their_tech_levels - our_tech_levels) / Sys_Max_Long(our_tech_levels, 1)

  // Almost always accept if there is a big gain
  if (net_tech_value >= 0.05) then
    set accept_tech_sharing := TRUE
  else
    // Approximately equal tech levels, considering other factors
    if (net_tech_value < 0.05) and (net_tech_value > -0.05) then
      if (coop_level >= COOP_LEVEL_MEDIUM) then
        set accept_tech_sharing := TRUE
      endif
    endif
  endif

  // Element 2 - Non-Aggression
  if (elem_type = TREATY_ELEMENT_TYPE_NON_AGGRESSION) then
    case elem_value
      1:
        // In neutral space (WIP)
        set useful_element := TRUE
      2:
        // All Systems (WIP)
        set useful_element := TRUE
      3:
        // Not useful if we breath the same atmosphere
        if (our_atmosphere_type = their_atmosphere_type) then
          set useful_element := FALSE
        endif
        // Not useful if they are close to us and better colonizers
        if (avg_sys_dist < lng_AI_Quadrant_Density) and (their_colonization_ability > our_colonization_ability) then
          set useful_element := FALSE
        endif
        // Not useful if they are a human player that's strong
        if (human_plr) and (fear_towards_plr > -5) then
          set useful_element := FALSE
        endif
    endcase
    // Flag that we were offered a non-aggression element
    if (elem_value >= 1) and (elem_value <= 3) then
      set gbl_treaty_has_non_aggression := TRUE
    endif
  endif

  // Element 3 - Mutual Defense Pact
  if (elem_type = TREATY_ELEMENT_TYPE_MUTUAL_DEFENSE_PACT) then
    // Not useful if we don't have the same primary enemy
    if (lng_Politics_Primary_Enemy <> Sys_Get_AI_Storage_Long(target_plr, 1, 3)) then
      set useful_element := FALSE
    endif
  endif

  // Element 4 - Migration
  if (elem_type = TREATY_ELEMENT_TYPE_ALLOW_MIGRATION_BETWEEN_COLONIES) then
    case elem_value
      1:
        // A>B
        // Not useful if we breath the same atmosphere
        if (our_atmosphere_type = their_atmosphere_type) then
          set useful_element := FALSE
        endif
      2:
        // B>A
        // Not useful if we breath the same atmosphere
        if (our_atmosphere_type = their_atmosphere_type) then
          set useful_element := FALSE
        endif
      3:
        // Allow
        // Not useful if we breath the same atmosphere
        if (our_atmosphere_type = their_atmosphere_type) then
          set useful_element := FALSE
        endif
        // Not useful with equivalent or stronger human players
        if (human_plr) and (fear_towards_plr > -5) then
          set useful_element := FALSE
        endif
    endcase
  endif

  // Element 6 - Share Resupply
  if (elem_type = TREATY_ELEMENT_TYPE_SHARE_RESUPPLY) then
    // Not useful if the player is too far away
    if (avg_sys_dist > lng_AI_Quadrant_Density) then
      set useful_element := FALSE
    endif
  endif

  // Element 7 - Share Repair
  if (elem_type = TREATY_ELEMENT_TYPE_SHARE_REPAIR) then
    // Not useful if the player is too far away
    if (avg_sys_dist > lng_AI_Quadrant_Density) then
      set useful_element := FALSE
    endif
  endif

  // Element 8 - Share Technology
  if (elem_type = TREATY_ELEMENT_TYPE_SHARE_TECHNOLOGY) then
    // Not useful if we're much better at research
    if (not accept_tech_sharing) then
      set useful_element := FALSE
    endif
    // Not useful if it's a human player that is weak
    if (human_plr) and (lst_Politics_Fear_Towards_Player.get(target_plr) < -5) then
      set useful_element := FALSE
    endif
  endif

  // Element 9 - Share Maps
  if (elem_type = TREATY_ELEMENT_TYPE_SHARE_SYSTEM_MAPS) then
    // Not useful if the player is close to us
    if (avg_sys_dist < lng_AI_Quadrant_Density) then
      set useful_element := FALSE
    endif
    // Don't share maps if we're an ancient race!
    if (bool_Race_Is_Ancient_Race) then
      set useful_element := FALSE
    endif
  endif

  // Element 10 - Share Communication Channels
  if (elem_type = TREATY_ELEMENT_TYPE_SHARE_COMMUNICATION_CHANNELS) then
    // Not useful if there are no unknown empires between us...
    if (not Difference_In_Known_Empires(target_plr, sys_long_Player_ID)) then
      set useful_element := FALSE
    endif
  endif

  // Element 11 - Share Espionage Information
  if (elem_type = TREATY_ELEMENT_TYPE_SHARE_ESPIONAGE_INFO) then
    // Not useful if it's not a human player
    if (not human_plr) then
      set useful_element := FALSE
    endif
  endif

  // Element 12 - Sensor Information
  if (elem_type = TREATY_ELEMENT_TYPE_SHARE_SENSOR_INFO) then
    // Not useful if the player is friends with our enemies or one of our other friends is an enemy of this player
    if Is_Empire_Friends_With_Enemies(target_plr) or Are_Our_Friends_Enemies_Of_Another_Friend(target_plr) then
      set useful_element := FALSE
    endif
  endif

  // Element 13 - Share Designs
  if (elem_type = TREATY_ELEMENT_TYPE_SHARE_DESIGNS) then
    // Not useful if the player is friends with our enemies
    if Is_Empire_Friends_With_Enemies(target_plr) then
      set useful_element := FALSE
    endif
    // Not useful if we don't have the same primary enemy
    if (lng_Politics_Primary_Enemy <> Sys_Get_AI_Storage_Long(target_plr, 1, 3)) then
      set useful_element := FALSE
    endif
  endif

  // Element 14 - Minefield Codes
  // Not useful if the player is not close to us
  if (elem_type = TREATY_ELEMENT_TYPE_SHARE_CODES_FOR_MINEFIELDS) then
    if (avg_sys_dist > lng_AI_Quadrant_Density) then
      set useful_element := FALSE
    endif
    // Consider sharing minefield codes if they are weaker and have a lot of marked mines
    if (lst_Politics_Fear_Towards_Player.get(target_plr) < -5) and (lst_AI_Enemy_Marked_Minefield_Count.get(target_plr) > 100) then
      set useful_element := TRUE
    endif
    // Flag that we were offered share both minefield codes element
    if (elem_value = 3) then
      set gbl_treaty_has_minefield_codes := TRUE
    endif
  endif

  // Element 15 - Share Combat Reports
  if (elem_type = TREATY_ELEMENT_TYPE_SHARE_COMBAT_REPORTS) then
    if (not human_plr) then
      set useful_element := FALSE
    endif
  endif

  // Element 16 - Cannot Do Research
  if (elem_type = TREATY_ELEMENT_TYPE_CANNOT_RESEARCH) then
    // Never useful unless we're at max tech
    if (not bool_Race_At_Max_Tech) or (human_plr) then
      set useful_element := FALSE
    endif
  endif

  // Element 17 - Cannot Do Intelligence
  if (elem_type = TREATY_ELEMENT_TYPE_CANNOT_INTELLIGENCE) then
    // Never useful unless it's a no intel game
    if (bool_Intel_Is_Allowed) or (human_plr) then
      set useful_element := FALSE
    endif
  endif

  // Element 19 - Consider not using viral weapons unless we want to
  if (elem_type = TREATY_ELEMENT_TYPE_CANNOT_USE_VIRAL_WEAPONS) then
    if Is_Component_Available("Toxic Injectors") or Is_Component_Available("Plague Bomb") or (bool_Race_Uses_Plague_Ships) or (bool_Enemy_Uses_Viral_Weapons) then
      set useful_element := TRUE
    else
      set useful_element := FALSE
    endif
  endif

  // Element 20 - Consider not using planet destroying weapons if we have them
  if (elem_type = TREATY_ELEMENT_TYPE_CANNOT_DESTROY_PLANETS) then
    if Is_Component_Available("Tectonic Bomb") or (bool_Enemy_Uses_Evil_Stellar_Manipulation) then
      set useful_element := TRUE
    else
      set useful_element := FALSE
    endif
  endif

  // Element 21 - Consider not using star destroying weapons if we have them
  if (elem_type = TREATY_ELEMENT_TYPE_CANNOT_DESTROY_STARS) then
    if Is_Component_Available("Stellar Nucleonic Torpedo") or (bool_Enemy_Uses_Evil_Stellar_Manipulation) then
      set useful_element := TRUE
    else
      set useful_element := FALSE
    endif
  endif

  // Element 22 - Consider not creating blackholes if we can
  if (elem_type = TREATY_ELEMENT_TYPE_CANNOT_CREATE_BLACKHOLES) then
    if Is_Component_Available("Inverted Quantum Beam") or (bool_Enemy_Uses_Evil_Stellar_Manipulation) then
      set useful_element := TRUE
    else
      set useful_element := FALSE
    endif
  endif

  // Element 23 - Consider not creating nebulae if we can
  if (elem_type = TREATY_ELEMENT_TYPE_CANNOT_CREATE_NEBULAE) then
    if Is_Component_Available("Nucleonic Thresher Torpedo") or (bool_Enemy_Uses_Evil_Stellar_Manipulation) then
      set useful_element := TRUE
    else
      set useful_element := FALSE
    endif
  endif

  // Element 24 - Consider not using cloaking if we can
  if (elem_type = TREATY_ELEMENT_TYPE_CANNOT_USE_CLOAKING) then
    if  Is_Component_Available("Cloaking Device") or (bool_Enemy_Uses_Cloaking_Devices) then
      set useful_element := TRUE
    else
      set useful_element := FALSE
    endif
  endif

  // Element 25 - Consider resource tariff
  if (elem_type = TREATY_ELEMENT_TYPE_RESOURCE_TARIFF) then
    if (fear_towards_plr < -5) or (fear_towards_plr > 5) then
      set useful_element := TRUE
    else
      set useful_element := FALSE
    endif
  endif

  return useful_element
end

//------------------------------------------------------------------------
// Get_Trade_To_Propose
//------------------------------------------------------------------------
function Get_Trade_To_Propose returns boolean
params
  to_plr:                    long
  new_log_id:                long
vars
  resource_get_type:         long
  resource_get_amount:       long
  resource_give_type:        long
  resource_give_amount:      long
  propose_trade:             boolean := FALSE
begin

  // Consider making a trade

  // Resources
  // Trade for Minerals
  if (bool_Race_Minerals_Low) then
    set resource_get_type := RESOURCE_TYPE_MINERALS
    // Organics for Minerals
    if (bool_Race_Organics_High) then
      set resource_give_type := RESOURCE_TYPE_ORGANICS
    else
      // Radioactives for Minerals
      if (bool_Race_Radioactives_High) then
        set resource_give_type := RESOURCE_TYPE_RADIOACTIVES
      endif
    endif
  else
    // Trade for Radioactives
    if (bool_Race_Radioactives_Low) then
      set resource_get_type := RESOURCE_TYPE_RADIOACTIVES
      // Organics for Radioactives
      if (bool_Race_Organics_High) then
        set resource_give_type := RESOURCE_TYPE_ORGANICS
      else
        // Minerals for Radioactives
        if (bool_Race_Minerals_High) then
          set resource_give_type := RESOURCE_TYPE_MINERALS
        endif
      endif
    else
      // Trade for Organics
      if (bool_Race_Organics_Low) then
        set resource_get_type := RESOURCE_TYPE_ORGANICS
        // Radioactives for Organics
        if (bool_Race_Radioactives_High) then
          set resource_give_type := RESOURCE_TYPE_RADIOACTIVES
        else
          // Minerals for Organics
          if (bool_Race_Minerals_High) then
            set resource_give_type := RESOURCE_TYPE_MINERALS
          endif
        endif
      endif
    endif
  endif

  // How much resources to trade?
  if (resource_give_type > 0) then
    // How much to trade?
    case resource_get_type
      RESOURCE_TYPE_MINERALS:
        set resource_get_amount := Sys_Trunc(lng_Minerals_Deficit / 1000) * 1000
      RESOURCE_TYPE_ORGANICS:
        set resource_get_amount := Sys_Trunc(lng_Organics_Deficit / 1000) * 1000
      RESOURCE_TYPE_RADIOACTIVES:
        set resource_get_amount := Sys_Trunc(lng_Radioactives_Deficit / 1000) * 1000
    endcase
    // Set minimum or maximum Cap
    set resource_get_amount := Sys_Max_Long(5000, resource_get_amount)
    set resource_get_amount := Sys_Min_Long(25000, resource_get_amount)
    // Give equal amount of other resource or slightly more
    set resource_give_amount := resource_get_amount + (Sys_Get_Random_Long(0, 2) * 1000)
  endif

  // Make the trade package
  if (resource_get_amount > 0) and (resource_give_amount > 0) then
    set propose_trade := Sys_Empire_Log_Add_Package_Items(new_log_id, PACKAGE_TYPE_GET, MESSAGE_PACKAGE_ITEM_TYPE_RESOURCE, resource_get_type, resource_get_amount)
    set propose_trade := Sys_Empire_Log_Add_Package_Items(new_log_id, PACKAGE_TYPE_GIVE, MESSAGE_PACKAGE_ITEM_TYPE_RESOURCE, resource_give_type, resource_give_amount)
  endif

  // Technology
  // Pending

  return propose_trade
end

//------------------------------------------------------------------------
// Get_Warning_Message_To_Send
//------------------------------------------------------------------------
function Get_Warning_Message_To_Send returns long
params
  new_log_id:                long
  to_plr:                    long
  other_plr:                 long byref
  target_system_id:          long byref
  target_sobj_id:            long byref
vars
  new_msg_type:              long
  lst_log_entries:           longlist
  log_id:                    long
  log_type:                  long
  list_count:                long
  list_index:                long
  sys_loc:                   long
  sect_loc:                  long
  plr_caused:                long
  other_plr1:                long
  other_plr2:                long
  other_plr3:                long
  other_plr4:                long
  loss_system:               long
  skip_request:              boolean
  is_friend:                 boolean
  is_good_friend:            boolean
  is_enemy:                  boolean
  is_war_enemy:              boolean
  has_defense_pact:          boolean := FALSE
  status_time:               long
  msg_time_mod:              long
  req_time_mod:              long
  wp_count:                  long
  wp_index:                  long
  wp_dest_sys:               long
  plr_count:                 long
  plr_index:                 long
  combat_lost:               boolean
  extra_parameter:           string
begin

  // Set variables
  set other_plr := 0
  set target_system_id := 0
  set target_sobj_id := 0

  // Is the player responsible an ally or an enemy
  set is_friend := (lst_Politics_Friendship_Towards_Player.get(to_plr) > lng_Politics_Friendship_Pts_Ok_Friend)
  set is_good_friend := (lst_Politics_Friendship_Towards_Player.get(to_plr) > lng_Politics_Friendship_Pts_Good_Friend)
  set is_enemy := Sys_Empire_Politics_Is_Player_Enemy(sys_long_Player_ID, to_plr)
  set is_war_enemy := (Sys_Empire_Politics_Get_Political_Status_Between_Players(sys_long_Player_ID, to_plr) = POLITICAL_STATUS_TYPE_WAR)
  set status_time := Sys_Empire_Politics_Get_Status_Time_With_Player(sys_long_Player_ID, to_plr)

  // Message frequency modifier
  case lng_AI_Categorization
    AI_CATEGORY_PEACEFUL:
      set msg_time_mod := Sys_Trunc(status_time ^ 0.5)
      set req_time_mod := 10
    AI_CATEGORY_NEUTRAL:
      set msg_time_mod := Sys_Trunc(status_time ^ 0.5)
      set req_time_mod := 8
    AI_CATEGORY_AGGRESSIVE:
      set msg_time_mod := Sys_Trunc(status_time ^ 0.5)
      set req_time_mod := 5
    AI_CATEGORY_XENOPHOBIC:
      set msg_time_mod := Sys_Trunc(status_time ^ 0.67)
      set req_time_mod := 5
  endcase

  // Check for other attributes
  set has_defense_pact := Do_We_Have_Treaty_Element_With_Player(to_plr, TREATY_ELEMENT_TYPE_MUTUAL_DEFENSE_PACT, FALSE, 0)

  // Check our empire log for events to generate demands/requests
  call Sys_Empire_Log_Get_Log_Entries_For_This_Turn(sys_long_Player_ID, lst_log_entries)
  set list_count := lst_log_entries.count()

  if (list_count > 0) then
    for list_index := 1 to list_count do
      if (new_msg_type = 0) then
        // Get log message parameters
        set log_id := lst_log_entries.get(list_index)
        set log_type := Sys_Empire_Log_Get_Log_Entry_Type(sys_long_Player_ID, log_id)
        set sys_loc := Sys_Empire_Log_Get_Log_Entry_System_Location(sys_long_Player_ID, log_id)
        set sect_loc := Sys_Empire_Log_Get_Log_Entry_Sector_Location(sys_long_Player_ID, log_id)
        set plr_caused := Sys_Empire_Log_Get_Log_Entry_Caused_By_Player(sys_long_Player_ID, log_id)
        set skip_request := FALSE
        call Sys_Get_Log_Players_In_Combat(sys_long_Player_ID, log_id, other_plr1, other_plr2, other_plr3, other_plr4)
        // Skip some types of requests if we are not involved in the combat
        if (sys_long_player_ID <> other_plr1) or (sys_long_player_ID <> other_plr2) or (sys_long_player_ID <> other_plr3) or (sys_long_player_ID <> other_plr4) then
          set skip_request := TRUE
        endif
        // Consider combat or intelligence events for requests/demands against our enemies
        if (is_enemy) or (is_war_enemy) then
          // Did we lose a combat?
          if (log_type = LOG_TYPE_GROUND_COMBAT_OFFENSE_LOST) or (log_type = LOG_TYPE_GROUND_COMBAT_DEFENSE_LOST) or (log_type = LOG_TYPE_SPACE_COMBAT_OFFENSE_LOST) or (log_type = LOG_TYPE_SPACE_COMBAT_DEFENSE_LOST) then
            set combat_lost := TRUE
          else
            set combat_lost := FALSE
          endif
          // Request enemy ships stop attacking (system specific, general)
          if (combat_lost) and (not skip_request) then
            if (sys_loc > 0) and (Sys_Get_Random_Long(1, 2) = 1) then
              set new_msg_type := POLITICS_MSG_REQUEST_STOP_SHIP_ATTACKS_IN_SYSTEM
              set target_system_id := sys_loc
            else
              set new_msg_type := POLITICS_MSG_REQUEST_STOP_MILITARY_ATTACKS_ON_US
            endif
          endif
          // Request enemies stop intelligence operations against us
          if (log_type = LOG_TYPE_ESPIONAGE_AGAINST_US) and (to_plr = plr_caused) then
            set new_msg_type := POLITICS_MSG_REQUEST_STOP_ESPIONAGE_AGAINST_US
          endif
          if (log_type = LOG_TYPE_SABOTAGE_AGAINST_US) and (to_plr = plr_caused) then
            set new_msg_type := POLITICS_MSG_REQUEST_STOP_SABOTAGE_AGAINST_US
          endif
        else
          // Request help from our good friends
          if (is_good_friend) then
            // Request help from our mutual defense partner if we've lost combats or are hit by intelligence attacks
            if (has_defense_pact) and (not skip_request) then
              if (log_type = LOG_TYPE_GROUND_COMBAT_DEFENSE_LOST) or (log_type = LOG_TYPE_SPACE_COMBAT_DEFENSE_LOST) then
                if (plr_caused > 0) then
                  // Specific request for military help
                  if (sys_loc > 0) and (Sys_Get_Random_Long(1, 2) = 1) then
                    set new_msg_type := POLITICS_MSG_REQUEST_MILITARY_ASSISTANCE_IN_SYSTEM
                    set target_system_id := sys_loc
                  else
                    set new_msg_type := POLITICS_MSG_REQUEST_MILITARY_ASSISTANCE_AGAINST_EMPIRE
                    set other_plr := plr_caused
                  endif
                else
                  // Generic request for military help
                  if (sys_loc > 0) and (Sys_Get_Random_Long(1, 2) = 1) then
                    set new_msg_type := POLITICS_MSG_REQUEST_MILITARY_ASSISTANCE_IN_SYSTEM
                    set target_system_id := sys_loc
                  else
                    set new_msg_type := POLITICS_MSG_REQUEST_MILITARY_ASSISTANCE
                    set other_plr := lng_Politics_Primary_Enemy
                  endif
                endif
              endif
              // Request help against intelligence attacks
              if (log_type = LOG_TYPE_ESPIONAGE_AGAINST_US) or (log_type = LOG_TYPE_SABOTAGE_AGAINST_US) then
                if (plr_caused > 0) and (Sys_Get_Random_Long(1, 2) = 1) then
                  set new_msg_type := POLITICS_MSG_REQUEST_INTELLIGENCE_ASSISTANCE_AGAINST_EMPIRE
                  set other_plr := plr_caused
                else
                  set new_msg_type := POLITICS_MSG_REQUEST_INTELLIGENCE_ASSISTANCE
                endif
              endif
            endif
            // Request economic help
            if (log_type = LOG_TYPE_CONSTRUCTION_NO_RESOURCES) or (log_type = LOG_TYPE_SHIP_DESTROYED_MAINT_NOT_PAYED) then
              if (bool_Race_Minerals_Low) or (bool_Race_Organics_Low) or (bool_Race_Radioactives_Low) then
                set new_msg_type := POLITICS_MSG_REQUEST_ECONOMIC_ASSISTANCE
              endif
            endif
          endif
        endif
      endif
    endfor
  endif

  // Request a gift from a weaker player
  if (new_msg_type = 0) then
    if (lst_Politics_Fear_Towards_Player.get(to_plr) < -20) and (Sys_Get_Random_Long(1, req_time_mod) = 1) then
      if Get_Gift_Items_To_Request(new_log_id, to_plr) then
        set new_msg_type := POLITICS_MSG_REQUEST_GIFT
      endif
    endif
  endif

  // Request a much weaker player surrender
  if (new_msg_type = 0) then
    if (is_enemy) and (lst_Politics_Fear_Towards_Player.get(to_plr) <= -40) and (Sys_Get_Random_Long(1, req_time_mod) = 1) then
      set new_msg_type := POLITICS_MSG_REQUEST_SURRENDER
    endif
  endif

  // Request technological assistance from a friend
  if (new_msg_type = 0) then
    if (is_good_friend) and ((bool_Enemy_Far_Ahead_In_Research) or (bool_Enemy_Ahead_In_Research)) and (Sys_Get_Random_Long(1, 15 - req_time_mod) = 1) then
      set new_msg_type := POLITICS_MSG_REQUEST_TECHNOLOGICAL_ASSISTANCE
    endif
  endif

  // Request that non-treaty players remove their ships from our systems
  if (new_msg_type = 0) then
    if (is_enemy) and (not is_war_enemy) then
      set list_count := lst_AI_Defense_Location_System.count()
      // Only consider non-treaty empires
      if (list_count > 0) then
        for list_index := 1 to list_count do
          if (new_msg_type = 0) then
            if (lst_AI_Defense_Location_Owner.get(list_index) = to_plr) and (Sys_Get_Random_Long(1, 5) < lst_Politics_Target_Player_Priority.get(to_plr)) then
              set new_msg_type := POLITICS_MSG_REQUEST_REMOVE_SHIPS_FROM_SYSTEM
              set target_system_id := lst_AI_Defense_Location_System.get(list_index)
              // Tag this location for our ships to follow up on
              call lst_AI_Request_Location_System.add(target_system_id)
            endif
          endif
        endfor
      endif
    endif
  endif

  // Request that non-treaty players remove their colonies from systems adjacent to our border colonies
  if (new_msg_type = 0) and (Sys_Get_Random_Long(1, 5) = 1) then
    if (is_enemy) and (not is_war_enemy) then
      set list_count := lst_AI_Border_System.count()
      set list_index := 0
      // Check adjacent systems to our border systems for enemy colonies
      if (list_count > 0) then
        loop
          set list_index := list_index + 1
          set sys_loc := lst_AI_Border_System.get(list_index)
          set wp_count := Sys_Get_Solar_System_Warp_Point_Count(sys_long_Player_ID, sys_loc)
          // Check the warp point destinations for systems with enemy colonies
          if (wp_count > 0) then
            loop
              set wp_index := wp_index + 1
              set wp_dest_sys := Sys_Get_Solar_System_Warp_Point_Dest_System(sys_long_Player_ID, sys_loc, wp_index)
              // Does our enemy have a colony in the destination system?
              if Sys_Player_Has_Colony_In_System(to_plr, wp_dest_sys) then
                set new_msg_type := POLITICS_MSG_REQUEST_REMOVE_COLONIES_FROM_SYSTEM
                set target_system_id := wp_dest_sys
                // Add location to follow up our request
                call lst_AI_Request_Location_System.add(target_system_id)
              endif
              exitwhen (wp_index >= wp_count) or (new_msg_type > 0)
            endloop
          endif
          exitwhen (list_index >= list_count) or (new_msg_type > 0)
        endloop
      endif
    endif
  endif

  // Request that our friends break treaties with our enemies
  if (new_msg_type = 0) then
    if (is_good_friend) and (Sys_Get_Random_Long(1, 10) < lng_AI_Categorization) then
      set plr_count := Sys_Get_Number_Of_Players()
      if (plr_count > 0) then
        for plr_index := 1 to plr_count do
          if (new_msg_type = 0) then
            if (plr_index <> sys_long_Player_ID) and (plr_index <> to_plr) then
              if Sys_Empire_Politics_Is_Player_Enemy(sys_long_Player_ID, plr_index) and Sys_Empire_Politics_Is_Player_Ally(to_plr, plr_index) then
                set new_msg_type := POLITICS_MSG_REQUEST_BREAK_TREATY_WITH_EMPIRE
                set other_plr := plr_index
              endif
            endif
          endif
        endfor
      endif
    endif
  endif

  // Request that our friends make peace with each other if they are enemies
  if (new_msg_type = 0) then
    if (is_good_friend) and (Sys_Get_Random_Long(1, 10) < (6 - lng_AI_Categorization)) then
      for plr_index := 1 to plr_count do 
        if (new_msg_type = 0) then
          if (plr_index <> to_plr) and (plr_index <> sys_long_Player_ID) then
            if Sys_Empire_Politics_Is_Player_Ally(sys_long_Player_ID, plr_index) then
              if (Sys_Empire_Politics_Get_Political_Status_Between_Players(plr_index, to_plr) = POLITICAL_STATUS_TYPE_WAR) then
                set new_msg_type := POLITICS_MSG_REQUEST_MAKE_PEACE_WITH_EMPIRE
                set other_plr := plr_index
              endif
            endif
          endif
        endif
      endfor
    endif
  endif

  // To Do
  // POLITICS_MSG_REQUEST_STOP_AGGRESSION_AGAINST_EMPIRE
  // POLITICS_MSG_REQUEST_STOP_MILITARY_ATTACKS_AGAINST_EMPIRE
  // POLITICS_MSG_REQUEST_STOP_ESPIONAGE_AGAINST_EMPIRE
  // POLITICS_MSG_REQUEST_STOP_SABOTAGE_AGAINST_EMPIRE

  // Send a general message from time to time to our friends/enemies and relative unknowns
  if (new_msg_type = 0) then
    if (Sys_Get_Random_Long(1, 5 + msg_time_mod) = 1) then
      // Friendly
      if ((is_friend) or (is_good_friend)) then
        set new_msg_type := POLITICS_MSG_GENERAL_MESSAGE
        set str_Override_Message := "Friend Miscellaneous Msg"
        set other_plr := lng_Politics_Primary_Enemy
      else
        // Known but no treaty for many turns or war
        if ((is_enemy and status_time > 50) or (is_war_enemy)) then
          set new_msg_type := POLITICS_MSG_GENERAL_MESSAGE
          set str_Override_Message := "Enemy Miscellaneous Msg"
        else
          // Known but no treaty or treaty with low friendship value
          set new_msg_type := POLITICS_MSG_GENERAL_MESSAGE
        endif
      endif
    endif
  endif

  // Add the specific details to the message if required
  if (other_plr > 0) then
    call Sys_Empire_Log_Set_Log_Entry_Message_Param_Against_Player(new_log_id, other_plr)
  endif
  if (target_system_id > 0) then
    call Sys_Empire_Log_Set_Log_Entry_Message_Param_Target_System(new_log_id, target_system_id)
  endif
  if (target_sobj_id > 0) then
    call Sys_Empire_Log_Set_Log_Entry_Message_Param_Target_Space_Object_ID(new_log_id, target_sobj_id)
  endif

  // Note the date and type of request
  if (new_msg_type > 0) then
    call lst_Date_Last_Request_Made.set(to_plr, sys_long_Game_Date)
    call lst_Last_Request_Made_Type.set(to_plr, new_msg_type)
  endif

  return new_msg_type
end

//------------------------------------------------------------------------
// Alliance_Voting
//------------------------------------------------------------------------
function Alliance_Voting returns boolean
params
vars
  our_alliance_id:           long
  num_proposals:             long
  prop_index:                long
  prop_status:               long
  prop_type:                 long
  our_vote:                  long
  plr_id:                    long
  num_plrs:                  long
  anger_towards_plr:         long
  fear_towards_plr:          long
  alliance_anger:            long
  proposal_added:            boolean
begin

  // Are we in an alliance?
  set our_alliance_id := Sys_Empire_Politics_In_Alliance_ID(sys_long_Player_ID)

  // Are there proposals for us to vote on?
  if (our_alliance_id > 0) then
    set num_proposals := Sys_Empire_Politics_Get_Alliance_Proposal_Count(our_alliance_id)

    if (num_proposals > 0) then
      for prop_index := 1 to num_proposals do
        set prop_status := Sys_Empire_Politics_Get_Alliance_Proposal_Status(our_alliance_id, prop_index)
        if (prop_status = PROPOSAL_STATUS_WAITING_FOR_VOTES) then
          set prop_type := Sys_Empire_Politics_Get_Alliance_Proposal_Type(our_alliance_id, prop_index)
          set our_vote := 0

          case prop_type
            PROPOSAL_TYPE_ADD_MEMBER:
              set plr_id := Sys_Empire_Politics_Get_Alliance_Proposal_Param(our_alliance_id, prop_index)
              set anger_towards_plr := lst_Politics_Anger_Towards_Player.get(plr_id)
              set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(plr_id)
              if (anger_towards_plr < lng_Politics_Alliance_Max_Anger_To_Add_Member - fear_towards_plr) then
                set our_vote := 1
              endif
            PROPOSAL_TYPE_REMOVE_MEMBER:
              set plr_id := Sys_Empire_Politics_Get_Alliance_Proposal_Param(our_alliance_id, prop_index)
              set anger_towards_plr := lst_Politics_Anger_Towards_Player.get(plr_id)
              set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(plr_id)
              if (anger_towards_plr >= lng_Politics_Alliance_Min_Anger_To_Remove_Member + fear_towards_plr) then
                set our_vote := 1
              endif
            PROPOSAL_TYPE_RULE_CHANGE:
              set plr_id := Sys_Empire_Politics_Get_Alliance_Proposal_Created_By_Plr(our_alliance_id, prop_index)
              set anger_towards_plr := lst_Politics_Anger_Towards_Player.get(plr_id)
              set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(plr_id)
              if (anger_towards_plr < lng_Politics_Alliance_Max_Anger_To_Accept_Rule_Change - fear_towards_plr) then
                set our_vote := 1
              endif
            PROPOSAL_TYPE_SEND_MESSAGE:
              set plr_id := Sys_Empire_Politics_Get_Alliance_Proposal_Created_By_Plr(our_alliance_id, prop_index)
              set anger_towards_plr := lst_Politics_Anger_Towards_Player.get(plr_id)
              set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(plr_id)
              if (anger_towards_plr < lng_Politics_Alliance_Max_Anger_To_Accept_Send_Message - fear_towards_plr) then
                set our_vote := 1
              endif
            PROPOSAL_TYPE_REPLY_TO_MESSAGE:
              set plr_id := Sys_Empire_Politics_Get_Alliance_Proposal_Created_By_Plr(our_alliance_id, prop_index)
              set anger_towards_plr := lst_Politics_Anger_Towards_Player.get(plr_id)
              set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(plr_id)
              if (anger_towards_plr < lng_Politics_Alliance_Max_Anger_To_Accept_Reply_Message - fear_towards_plr) then
                set our_vote := 1
              endif
          endcase
          // Submit our vote on the proposal
          call Sys_Empire_Politics_Vote_Alliance_Proposal(our_alliance_id, prop_index, sys_long_Player_ID, our_vote)
        endif
      endfor
    else
      // Should we propose something ourselves?
      if (Sys_Get_Random_Long(1, 5) = 1) then

        set num_plrs := Sys_Get_Number_Of_Players()
        set proposal_added := FALSE
        
        // Should we propose to add another player to the alliance?
        if (not proposal_added) then
          for plr_id := 1 to num_plrs do
            if (plr_id <> sys_long_Player_ID) and (Sys_Empire_Politics_In_Alliance_ID(plr_id) = 0) and Sys_Empire_Politics_Is_Player_Known(sys_long_Player_ID, plr_id) then
              set anger_towards_plr := lst_Politics_Anger_Towards_Player.get(plr_id)
              set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(plr_id)
              set alliance_anger := Sys_Empire_Politics_Get_Alliance_Anger_Towards_Player(our_alliance_id, plr_id)
              if (anger_towards_plr < lng_Politics_Alliance_Max_Anger_To_Add_Member - fear_towards_plr) and (alliance_anger < lng_Politics_Alliance_Max_Anger_To_Add_Member) then
                set proposal_added := TRUE
                call Sys_Empire_Politics_Add_Alliance_Proposal(our_alliance_id, sys_long_Player_ID, PROPOSAL_TYPE_ADD_MEMBER, plr_id)
              endif
            endif
          endfor
        endif

        // Should we propose to remove another player from the alliance?
        if (not proposal_added) then
          for plr_id := 1 to num_plrs do
            if (plr_id <> sys_long_Player_ID) and (Sys_Empire_Politics_In_Alliance_ID(plr_id) = our_alliance_id) then
              set anger_towards_plr := lst_Politics_Anger_Towards_Player.get(plr_id)
              set fear_towards_plr := lst_Politics_Fear_Towards_Player.get(plr_id)
              set alliance_anger := Sys_Empire_Politics_Get_Alliance_Anger_Towards_Player(our_alliance_id, plr_id)
              if (anger_towards_plr >= lng_Politics_Alliance_Min_Anger_To_Remove_Member + fear_towards_plr) and (alliance_anger >= lng_Politics_Alliance_Min_Anger_To_Remove_Member) then
                set proposal_added := TRUE
                call Sys_Empire_Politics_Add_Alliance_Proposal(our_alliance_id, sys_long_Player_ID, PROPOSAL_TYPE_REMOVE_MEMBER, plr_id)
              endif
            endif
          endfor
        endif
      endif
    endif
  endif

  return TRUE
end

//------------------------------------------------------------------------